using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;//For menu commands

using System.Drawing;
//using System.Drawing.Printing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Camalon.Drawing;


using System.Runtime.InteropServices;

namespace Camalon.Drawing.Design
{
	/// <summary>
	/// Summary description for RulingPanel.
	/// </summary>
	internal class RulingPanel : System.Windows.Forms.UserControl
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		Color	_gridColor				= Color.Silver;
		Pen		_linePenBase			= new Pen(Color.FromArgb(96,Color.Silver),1.0f);
		Pen		_linePenBold			= new Pen(Color.FromArgb(196,Color.Silver),1.0f);

		Ruler	_hRuler					= null;
		Ruler	_vRuler					= null;

		Size	_gridSize				= new Size(10,10);
		int		_gridPageSize			= 5;
		bool	_snapToGrid				= true;
		bool	_drawGrid				= true;
		Point	_prevScrollPos			= new Point(0,0);
		int		_outlineWidth			= ShapeAdornment.AdornmentMargin;


		//[DesignOnly(true)]
		ShapeContainerRootDesignerBase  _rootDesigner	= null;


		public RulingPanel()
		{
			// This call is required by the Windows.Forms Form Designer.
			SetStyle(System.Windows.Forms.ControlStyles.DoubleBuffer, true);
			SetStyle(System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true);
			SetStyle(System.Windows.Forms.ControlStyles.ResizeRedraw, true);
			SetStyle(System.Windows.Forms.ControlStyles.UserPaint, true);
			SetStyle(System.Windows.Forms.ControlStyles.SupportsTransparentBackColor, true);

			InitializeComponent();

			this.BackColor = Color.Transparent;
			//this.InvalidateRulers();
			this.AllowDrop = true;


		}


		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if( components != null )
					components.Dispose();
			}

			_linePenBase.Dispose();
			_linePenBold.Dispose();
			
			RemoveRootDesignerEvents();
			base.Dispose( disposing );
		}


		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			// 
			// RulingPanel
			// 
			this.AutoScroll = true;
			this.Name = "RulingPanel";
			this.Size = new System.Drawing.Size(93, 93);
		}
		#endregion



		protected internal bool  VScrollVisible
		{
			get{ return this.VScroll; }
		}

		protected internal Ruler VRuler
		{
			get{ return _vRuler; }
			set
			{ 
				_vRuler = value;
				SetRulerColors();
				_vRuler.Invalidate(false);
			}
		}

		protected internal Ruler HRuler
		{
			get{ return _hRuler; }
			set
			{ 
				_hRuler = value;
				SetRulerColors();
				_hRuler.Invalidate(false);
			}
		}



		private void ResetRulerRanges()
		{

			if( _rootDesigner == null) return;
			if( _vRuler == null || _hRuler== null) return;

			IShapeContainerProvider containerProvider = _rootDesigner.ShapeContainerProvider;
			if( containerProvider == null) return;

			Rectangle bounds = Rectangle.Round( _rootDesigner.ShapeContainer.Bounds );
			Shape primary = _rootDesigner.SelectionService.PrimarySelection as Shape;
			
			
			if( primary != null && primary != _rootDesigner.ShapeContainer ) 
				bounds = Rectangle.Round( primary.GetPathBounds());

			_vRuler.Range = new Point( bounds.Top,bounds.Bottom );;
			_hRuler.Range = new Point( bounds.Left, bounds.Right);
	

		}
		


		private void InvalidateRulers()
		{
			if( _vRuler != null) _vRuler.Invalidate(false);
			if( _hRuler != null) _hRuler.Invalidate(false);
		}

		private void SetRulerColors()
		{
			if(_vRuler != null)
			{
				_vRuler.BorderColor = _linePenBold.Color;
				_vRuler.BackColor	= _linePenBase.Color;
			}

			if(_hRuler != null)
			{
				_hRuler.BorderColor = _linePenBold.Color;
				_hRuler.BackColor	= _linePenBase.Color;
			}
		}

		[Category("Design")]
		[DefaultValue(typeof(Size),"10,10")]
		public Size GridSize
		{
			get
			{	
				return _gridSize;
			}
			set
			{
				_gridSize = value;
				this.Invalidate(false);
				this.InvalidateRulers();
			}
		}

		[Category("Design")]
		[DefaultValue(true)]
		public bool DrawGrid
		{
			get
			{	
				return _drawGrid;
			}
			set
			{
				_drawGrid = value;

				this.Invalidate(false);
				this.InvalidateRulers();
			}
		}

		[Category("Design")]
		[DefaultValue(5)]
		public int GridPageSize
		{
			get { return _gridPageSize;}
			set
			{
				_gridPageSize = value;
				this.Invalidate(false);
				this.InvalidateRulers();

			}
		}
		
		[Category("Design")]
		[DefaultValue(true)]
		public bool SnapToGrid
		{
			get
			{	
				return _snapToGrid;
			}
			set
			{
				_snapToGrid = value;
			}
		}

		[Category("Design")]
		[DefaultValue(typeof(Color), "Silver")]
		public Color GridColor
		{
			get
			{
				return _gridColor;
			}
			set
			{
				_gridColor = value;

				if( _linePenBase != null) { _linePenBase.Dispose(); _linePenBase = null;}
				if( _linePenBold != null) { _linePenBold.Dispose(); _linePenBold = null;}

				_linePenBase	= new Pen(Color.FromArgb(96,value),1.0f);
				_linePenBold	= new Pen(Color.FromArgb(196,value),1.0f);



				SetRulerColors();
				this.Invalidate(false);
				this.InvalidateRulers();

			}

		}


		#region Add/Remove Root Designer Events

		private void AddRootDesignerEvents()
		{
			if( _rootDesigner != null)
			{
				//FileWatcher.WriteLine("RulingPanel::AddRootDesignerEvents called");
				IDesignerHost host	= _rootDesigner.DesignerHost;
				host.Activated		+=new EventHandler(DesignerHostActivated);
				host.Deactivated	+=new EventHandler(DesignerHostDeactivated);

				_rootDesigner.ShapeContainer.InternalChanged			+=new EventHandler(ShapeInternalChanged);
				_rootDesigner.ShapeContainer.ShapeInternalChanged		+=new EventHandler(ShapeInternalChanged);
				_rootDesigner.ShapeContainer.ShapePathBoundsChanged		+=new ValueChangeEventHandler(ShapePathBoundsChanged);
				_rootDesigner.ShapeContainer.BoundsChanged				+=new ValueChangeEventHandler(ShapeContainerBoundsChanged);
				_rootDesigner.ShapeContainer.PathBoundsChanged			+=new ValueChangeEventHandler(ShapeContainerPathBoundsChanged);

			}
		}
		
		private void RemoveRootDesignerEvents()
		{
			if( _rootDesigner != null)
			{
				//FileWatcher.WriteLine("RulingPanel::RemoveRootDesignerEvents called");

				_rootDesigner.ShapeContainer.ShapeInternalChanged			-=new EventHandler(ShapeInternalChanged);
				_rootDesigner.ShapeContainer.ShapePathBoundsChanged			-=new ValueChangeEventHandler(ShapePathBoundsChanged);
				_rootDesigner.ShapeContainer.InternalChanged				-=new EventHandler(ShapeInternalChanged);
				_rootDesigner.ShapeContainer.BoundsChanged					-=new ValueChangeEventHandler(ShapeContainerBoundsChanged);
				_rootDesigner.ShapeContainer.PathBoundsChanged				-=new ValueChangeEventHandler(ShapeContainerPathBoundsChanged);

				IDesignerHost host	= _rootDesigner.DesignerHost;
				host.Activated		-=new EventHandler(DesignerHostActivated);
				host.Deactivated	-=new EventHandler(DesignerHostDeactivated);
			
			}
		}

		#endregion Add/Remove Root Designer Events

		private void DesignerHostActivated(object sender, EventArgs e)
		{
			////FileWatcher.WriteLine( "DesignerHostActivated called");

			UpdateMenuStatus();

		}

		private void DesignerHostDeactivated(object sender, EventArgs e)
		{
			////FileWatcher.WriteLine( "DesignerHostDeactivated called");
		}

		protected internal void SetRootDesigner( ShapeContainerRootDesignerBase rootDesigner, MenuCommandsHelper mcs)
		{
			RemoveRootDesignerEvents();
			_rootDesigner = rootDesigner;
			_mcs = mcs;//_rootDesigner.MenuCommandService;
			AddRootDesignerEvents();
			InitializeMenuCommands();
			RecalculateScrollSize();

            ResetRulerRanges();
			this.Invalidate( true );
			
		}


		private ShapeAdornment Adornment( Shape  shape )
		{
            if (shape == null) return null; 
            if (_rootDesigner == null) return null;


			return _rootDesigner.GetAdornment( shape);
		}


		#region MENU COMMAND SERVICE

		MenuCommandsHelper	_mcs		= null;

		private void InitializeMenuCommands()
		{
			if( _rootDesigner == null) return;
			if( _mcs == null) return;

			// SendToBack/BringToFront
			_mcs[MenuCommands.SendToBack				].Change += new EventHandler(OnSentToBack);
			_mcs[MenuCommands.BringToFront				].Change += new EventHandler(OnBringToFront);

			//KeyMove
			_mcs[MenuCommands.KeyMoveLeft				].Change += new EventHandler(OnKeyMoveLeft);
			_mcs[MenuCommands.KeyMoveRight				].Change += new EventHandler(OnKeyMoveRight);
			_mcs[MenuCommands.KeyMoveUp					].Change += new EventHandler(OnKeyMoveUp);
			_mcs[MenuCommands.KeyMoveDown				].Change += new EventHandler(OnKeyMoveDown);
			
			//KeyNudges
			_mcs[MenuCommands.KeyNudgeDown				].Change += new EventHandler(OnKeyNudgeDown);
			_mcs[MenuCommands.KeyNudgeLeft				].Change += new EventHandler(OnKeyNudgeLeft);
			_mcs[MenuCommands.KeyNudgeRight				].Change += new EventHandler(OnKeyNudgeRight);			
			_mcs[MenuCommands.KeyNudgeUp				].Change += new EventHandler(OnKeyNudgeUp);
		
			_mcs[MenuCommands.KeyNudgeHeightIncrease	].Change += new EventHandler(OnKeyNudgeHeightIncrease);
			_mcs[MenuCommands.KeyNudgeHeightDecrease	].Change += new EventHandler(OnKeyNudgeHeightDecrease);
			_mcs[MenuCommands.KeyNudgeWidthIncrease		].Change += new EventHandler(OnKeyNudgeWidthIncrease);			
			_mcs[MenuCommands.KeyNudgeWidthDecrease		].Change += new EventHandler(OnKeyNudgeWidthDecrease);	

			// Key Size
			_mcs[MenuCommands.KeySizeHeightIncrease		].Change += new EventHandler(OnKeySizeHeightIncrease);
			_mcs[MenuCommands.KeySizeHeightDecrease		].Change += new EventHandler(OnKeySizeHeightDecrease);	
			_mcs[MenuCommands.KeySizeWidthIncrease		].Change += new EventHandler(OnKeySizeWidthIncrease);
			_mcs[MenuCommands.KeySizeWidthDecrease		].Change += new EventHandler(OnKeySizeWidthDecrease);
			

			//KeyCancel
			_mcs[MenuCommands.KeyCancel					].Change += new EventHandler(OnKeyCancel);


			// Shape Align
			_mcs[MenuCommands.AlignLeft					].Change +=new EventHandler(OnAlignLeft);
			_mcs[MenuCommands.AlignBottom				].Change +=new EventHandler(OnAlignBottom);
			_mcs[MenuCommands.AlignHorizontalCenters	].Change +=new EventHandler(OnAlignHorizontalCenters);
			_mcs[MenuCommands.AlignRight				].Change +=new EventHandler(OnAlignRight);
			_mcs[MenuCommands.AlignToGrid				].Change +=new EventHandler(OnAlignToGrid);
			_mcs[MenuCommands.AlignTop					].Change +=new EventHandler(OnAlignTop);
			_mcs[MenuCommands.AlignVerticalCenters		].Change +=new EventHandler(OnAlignVerticalCenters);

			_mcs[MenuCommands.CenterHorizontally		].Change +=new EventHandler(OnCenterHorizontally);
			_mcs[MenuCommands.CenterVertically			].Change +=new EventHandler(OnCenterVertically);

			_mcs[MenuCommands.HorizSpaceConcatenate		].Change +=new EventHandler(OnHorizSpaceConcatenate);
			_mcs[MenuCommands.HorizSpaceDecrease		].Change +=new EventHandler(OnHorizSpaceDecrease);
			_mcs[MenuCommands.HorizSpaceIncrease		].Change +=new EventHandler(OnHorizSpaceIncrease);
			_mcs[MenuCommands.HorizSpaceMakeEqual		].Change +=new EventHandler(OnHorizSpaceMakeEqual);

			_mcs[MenuCommands.SizeToControlHeight		].Change +=new EventHandler(OnSizeToControlHeight);
			_mcs[MenuCommands.SizeToControl				].Change +=new EventHandler(OnSizeToControl);
			_mcs[MenuCommands.SizeToControlWidth		].Change +=new EventHandler(OnSizeToControlWidth);
			_mcs[MenuCommands.SizeToGrid				].Change +=new EventHandler(OnSizeToGrid);

			_mcs[MenuCommands.VertSpaceConcatenate		].Change +=new EventHandler(OnVertSpaceConcatenate);
			_mcs[MenuCommands.VertSpaceDecrease			].Change +=new EventHandler(OnVertSpaceDecrease);
			_mcs[MenuCommands.VertSpaceIncrease			].Change +=new EventHandler(OnVertSpaceIncrease);
			_mcs[MenuCommands.VertSpaceMakeEqual		].Change +=new EventHandler(OnVertSpaceMakeEqual);



			UpdateMenuStatus();
		}


		private void UpdateMenuStatus()
		{
			if( _rootDesigner == null) return;
			ISelectionService ss = _rootDesigner.SelectionService;
			bool isRootSelected = false;
			int selectedCount = 0;

			Shape primaryShape = ss.PrimarySelection as Shape;
			
			if( ss != null && ss.SelectionCount > 0 )
			{
				IList selectedComponents = (IList)ss.GetSelectedComponents();
				
				isRootSelected = selectedComponents[0] == _rootDesigner.ShapeContainer;
			
				foreach( object shapeObject in selectedComponents ) 
				if( shapeObject is Shape ) selectedCount++;		

			}

			if( _mcs != null)
			{
				_mcs[MenuCommands.BringToFront].Enabled				= 
				_mcs[MenuCommands.SendToBack].Enabled				= !isRootSelected && selectedCount > 0;

				_mcs[MenuCommands.AlignLeft	].Enabled				=
				_mcs[MenuCommands.AlignBottom].Enabled				=
				_mcs[MenuCommands.AlignHorizontalCenters].Enabled	=
				_mcs[MenuCommands.AlignRight].Enabled				= 
				_mcs[MenuCommands.AlignTop].Enabled					= 
				_mcs[MenuCommands.AlignVerticalCenters].Enabled		=

				_mcs[MenuCommands.CenterHorizontally].Enabled		=
				_mcs[MenuCommands.CenterVertically].Enabled			= !isRootSelected && selectedCount >= 1;

				_mcs[MenuCommands.HorizSpaceConcatenate	].Enabled	=
				_mcs[MenuCommands.HorizSpaceDecrease].Enabled		=
				_mcs[MenuCommands.HorizSpaceIncrease].Enabled		= 
				_mcs[MenuCommands.HorizSpaceMakeEqual].Enabled		= 

				_mcs[MenuCommands.SizeToControlHeight].Enabled		= 
				_mcs[MenuCommands.SizeToControl	].Enabled			=
				_mcs[MenuCommands.SizeToControlWidth].Enabled		= 

				_mcs[MenuCommands.VertSpaceConcatenate].Enabled		=
				_mcs[MenuCommands.VertSpaceDecrease].Enabled		=
				_mcs[MenuCommands.VertSpaceIncrease].Enabled		= 
				_mcs[MenuCommands.VertSpaceMakeEqual].Enabled		= !isRootSelected && selectedCount > 1;

				_mcs[MenuCommands.AlignToGrid].Enabled				= 
				_mcs[MenuCommands.SizeToGrid].Enabled				= selectedCount > 0;

			}

		}


		private void ShowContextMenu( Point mouseUp )
		{
			if( _mcs == null) return;

			Point ptTransform	= TransformPoint( mouseUp );

			Shape hitShape		= this.HitTest(ptTransform, false);

			UpdateMenuStatus();

			Point ptScreen = this.PointToScreen( mouseUp );

			if( hitShape != null && hitShape != _rootDesigner.ShapeContainer)
				_mcs.ShowSelectionMenu(ptScreen);
			else _mcs.ShowContainerMenu(ptScreen );


		}


		protected override bool ProcessDialogKey(Keys keyData)
		{
			if (_rootDesigner == null) return base.ProcessDialogKey(keyData);

//			this.Focus();
			//-------------------------------------------------------------------------------------------
			//In VS 2005 somehow this control looeses focus and some key menu commands are not been fired.
			//In 2003 use menu commands are OK...
			//-------------------------------------------------------------------------------------------	
			if( Control.ModifierKeys == Keys.Control)// (keyData & Keys.Control ) > 0)
			{
//				FileWatcher.WriteLine("ModifierKey = CONTROL + " + System.Enum.GetName( typeof(Keys), keyData));
				if (keyData == Keys.Down )	OnKeyNudgeDown(null, null);
				if (keyData == Keys.Up )	OnKeyNudgeUp(null, null);
				if (keyData == Keys.Left )	OnKeyNudgeLeft(null, null);
				if (keyData == Keys.Right )	OnKeyNudgeRight(null, null);

				return false;
			}
			else if( Control.ModifierKeys == Keys.Shift)//(keyData & Keys.Shift) > 0)
			{
//				FileWatcher.WriteLine("ModifierKey = SHIFT + " + System.Enum.GetName( typeof(Keys), keyData));
				if (keyData == Keys.Down )	OnKeyNudgeHeightIncrease(null, null);
				if (keyData == Keys.Up )	OnKeyNudgeHeightDecrease(null, null);
				if (keyData == Keys.Left )	OnKeyNudgeWidthIncrease(null, null);
				if (keyData == Keys.Right )	OnKeyNudgeWidthDecrease(null, null);
		
				return false;
			}
			else if( (Control.ModifierKeys & Keys.Shift) > 0 && (Control.ModifierKeys & Keys.Control) > 0)
			{
//				FileWatcher.WriteLine("ModifierKey = SHIFT + CONTROL + " + System.Enum.GetName( typeof(Keys), keyData));
				if (keyData == Keys.Down)	OnKeySizeHeightIncrease(null, null);
				if (keyData == Keys.Up)		OnKeySizeHeightDecrease(null, null);
				if (keyData == Keys.Left)	OnKeySizeWidthIncrease(null, null);
				if (keyData == Keys.Right)	OnKeySizeWidthDecrease(null, null);

				return false;
			}
			else if( Control.ModifierKeys == Keys.None )
			{
//				FileWatcher.WriteLine("ModifierKey = NONE + " + System.Enum.GetName( typeof(Keys), keyData));
				if (keyData == Keys.Down)	OnKeyMoveDown(null, null);
				if (keyData == Keys.Up)		OnKeyMoveUp(null, null);
				if (keyData == Keys.Left)	OnKeyMoveLeft(null, null);
				if (keyData == Keys.Right)	OnKeyMoveRight(null, null);

				if (keyData == Keys.Down ||
					keyData == Keys.Up ||
					keyData == Keys.Left ||
					keyData == Keys.Right) return true;

			}


//			this.Focus();
			return base.ProcessDialogKey(keyData);
		}


		PropertyDescriptor	_shapePropPos	 = TypeDescriptor.GetProperties(typeof( Shape ))["Position"];
		PropertyDescriptor	_shapePropSize	 = TypeDescriptor.GetProperties(typeof( Shape ))["Size"];

		#region Key Move Shapes

		private void KeyMoveShapes( Point offset , bool snapToGrid )
		{
			ISelectionService ss = _rootDesigner.SelectionService;
			IList selectedShapes = (IList)ss.GetSelectedComponents();

			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Shapes moved"))
			{
				foreach( object shapeObject in selectedShapes ) 
					if( shapeObject is Shape)
					{
						Shape shape = (Shape)shapeObject;

						Point pos = shape.Position;
						pos.X += offset.X;
						pos.Y += offset.Y;

						if( snapToGrid ) 
						{
							pos = this.SnapGridPoint( pos );
							if( offset.X == 0) pos.X = shape.Position.X;
							if( offset.Y == 0) pos.Y = shape.Position.Y;
						}

						if( pos != shape.Position ) {_shapePropPos.SetValue(shape,pos);commit = true;}
					}

				if( commit) tx.Commit();
				else tx.Cancel();
			}

			if( commit ) this.Invalidate(false);

		}


		private void OnKeyMoveLeft(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyMoveLeft");
			//int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyMoveShapes( new Point(-1,0 ), _snapToGrid);
		}

		private void OnKeyMoveRight(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyMoveRight");
			int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyMoveShapes(new Point(offset,0), _snapToGrid);
		}

		private void OnKeyMoveDown(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyMoveDown");
			int offset = _snapToGrid ? _gridSize.Height : 1;
			KeyMoveShapes(new Point(0,offset), _snapToGrid);
		}

		private void OnKeyMoveUp(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyMoveRight");
			//int offset = _snapToGrid ? _gridSize.Height : 1;
			KeyMoveShapes(new Point(0,-1), _snapToGrid);
		}


		private void OnKeyNudgeLeft(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyNudgeLeft");
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyMoveShapes( new Point(-offset,0 ), !_snapToGrid);

		}

		private void OnKeyNudgeRight(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyNudgeRight");
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyMoveShapes(new Point(offset,0), !_snapToGrid);

		}

		private void OnKeyNudgeDown(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyNudegeDown");
			int offset = !_snapToGrid ? _gridSize.Height : 1;
			KeyMoveShapes(new Point(0,offset), !_snapToGrid);

		}

		private void OnKeyNudgeUp(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyNudgeUp");
			int offset = !_snapToGrid ? _gridSize.Height : 1;
			KeyMoveShapes(new Point(0,-offset), !_snapToGrid);

		}


		#endregion Key Move Shapes


		#region Key Resize Shapes

		private void KeyResizeShapes( Size offset , bool snapToGrid )
		{
			ISelectionService ss = _rootDesigner.SelectionService;
			IList selectedShapes = (IList)ss.GetSelectedComponents();

			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Shapes resized"))
			{
				foreach( object shapeObject in selectedShapes ) 
					if( shapeObject is Shape)
					{
						Shape shape = (Shape)shapeObject;

						Size size = shape.Size;
						size.Width	+= offset.Width;
						size.Height += offset.Height;

						if( snapToGrid )
						{
							Point pos = shape.Position;
							Point dSize = new Point( size );
							dSize.Offset( pos.X, pos.Y );
							dSize = this.SnapGridPoint( dSize );
							dSize.Offset( -pos.X, -pos.Y );
							
							size = new Size( dSize );

							if( offset.Width == 0)	size.Width	= shape.Size.Width;
							if( offset.Height == 0) size.Height = shape.Size.Height;
						}
						
						if( size != shape.Size ) {_shapePropSize.SetValue(shape,size);commit = true;}
					}

				if( commit) tx.Commit();
				else tx.Cancel();
				
			}

			if( commit ) this.Invalidate(false);

		}



		private void OnKeySizeWidthDecrease(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeySizeWidthDecrease");
			//int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyResizeShapes( new Size(-1,0 ), _snapToGrid);

		}

		private void OnKeySizeWidthIncrease(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeySizeWidthIncrease");
			int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyResizeShapes(new Size(offset,0), _snapToGrid);
		}

		private void OnKeySizeHeightDecrease(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeySizeHeightDecrease");
			//int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyResizeShapes(new Size(0,-1), _snapToGrid);

		}

		private void OnKeySizeHeightIncrease(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeySizeHeightIncrease");
			int offset = _snapToGrid ? _gridSize.Height : 1;
			KeyResizeShapes(new Size(0,offset), _snapToGrid);
		}


		private void OnKeyNudgeWidthDecrease(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyNudgeWidthDecrease");
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyResizeShapes( new Size(-offset,0 ), !_snapToGrid);
		}

		private void OnKeyNudgeWidthIncrease(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyNudgeWidthIncrease");
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyResizeShapes(new Size(offset,0), !_snapToGrid);
		}

		private void OnKeyNudgeHeightDecrease(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyNudgeHeightDecrease");
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyResizeShapes(new Size(0,-offset), !_snapToGrid);
		}

		private void OnKeyNudgeHeightIncrease(object sender, EventArgs e)
		{
			//			FileWatcher.WriteLine( "KeyNudgeHeightIncrease");
			int offset = !_snapToGrid ? _gridSize.Height : 1;
			KeyResizeShapes(new Size(0,offset), !_snapToGrid);
		}


		#endregion Key Resize Shapes


		private void OnKeyCancel(object sender, EventArgs e)
		{
			if( _dragDropData != null) EscapeCommit();
		}


		private void OnBringToFront(object sender, EventArgs e)
		{
			if(_rootDesigner == null) return;

			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss == null || ss.SelectionCount == 0 ) return;

			ICollection selectedComponents = ss.GetSelectedComponents();
			PropertyDescriptor shapeIndexProp = TypeDescriptor.GetProperties( typeof(Shape) )["ShapeIndex"];
			using(DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Bring shape to front"))
			{
				foreach( object shapeObject in selectedComponents ) 
					if( shapeObject is Shape )
					{
						Shape shape = (Shape)shapeObject;
						int newIndex	= _rootDesigner.ShapeContainer.Shapes.Count-1;//To end

						shapeIndexProp.SetValue( shape, newIndex	);
					}
				tx.Commit();
			}

			this.Invalidate(false);

		}

		private void OnSentToBack(object sender, EventArgs e)
		{
			if(_rootDesigner == null) return;

			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss == null || ss.SelectionCount == 0 ) return;

			ICollection selectedComponents = ss.GetSelectedComponents();
			PropertyDescriptor shapeIndexProp = TypeDescriptor.GetProperties( typeof(Shape))["ShapeIndex"];
			using(DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Send shape to back"))
			{
				foreach( object shapeObject in selectedComponents ) 
					if( shapeObject is Shape )
					{
						Shape shape = (Shape)shapeObject;
						shapeIndexProp.SetValue( shape, 0);
					}
				tx.Commit();
			}

			this.Invalidate(false);

		}


		private void AlignTopLeft( bool alignLeft )
		{
			ISelectionService ss = _rootDesigner.SelectionService;
			Shape primShape = ss.PrimarySelection as Shape;
			if( primShape == null || primShape == _rootDesigner.ShapeContainer) return;

			IList selectedShapes = (IList)ss.GetSelectedComponents();
			if( selectedShapes.Count == 0) return;
	
			Point primPos = primShape.Position;

			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Align shape"))
			{
				foreach( object shapeObject in selectedShapes )
					if( shapeObject is Shape && shapeObject != primShape )
					{
						Shape shape = (Shape)shapeObject;
						Point pos = shape.Position;
						if( alignLeft ) pos.X = primPos.X;
						else  pos.Y = primPos.Y;


						if( pos != shape.Position ) { _shapePropPos.SetValue(shape,pos); commit = true;}
					}

				if( commit ) tx.Commit();
				else tx.Cancel();
			}

			if( commit ) this.Invalidate(false);
		}

		private void AlignRightBottom( bool alignRight )
		{
			ISelectionService ss = _rootDesigner.SelectionService;
			Shape primShape = ss.PrimarySelection as Shape;
			if( primShape == null || primShape == _rootDesigner.ShapeContainer) return;

			IList selectedShapes = (IList)ss.GetSelectedComponents();
			if( selectedShapes.Count == 0) return;
		
			Rectangle primBounds = Rectangle.Round( primShape.Bounds );

			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Align Shape"))
			{
				foreach( object shapeObject in selectedShapes )
					if( shapeObject is Shape && shapeObject != primShape )
					{
						Shape shape = (Shape)shapeObject;
						Rectangle bounds = Rectangle.Round( shape.Bounds );
						Point pos  = bounds.Location;

						if( alignRight ) 
						{
								
							int dx = bounds.Right - primBounds.Right;
							pos.X -= dx;
						}
						else  
						{
							int dy = bounds.Bottom - primBounds.Bottom;
							pos.Y -= dy;
						}

						if( pos != shape.Position ) { _shapePropPos.SetValue(shape,pos); commit = true;}
					}

				if( commit ) tx.Commit();
				else tx.Cancel();
			}

			if( commit ) this.Invalidate(false);
		}


		private void OnAlignToGrid(object sender, EventArgs e)
		{
			ISelectionService ss = _rootDesigner.SelectionService;
			Shape primShape = ss.PrimarySelection as Shape;
			if( primShape == null) return;

			IList selectedShapes = (IList)ss.GetSelectedComponents();
			if( selectedShapes.Count == 0) return;
			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Shapes moved"))
			{
				foreach( object shapeObject in selectedShapes ) 
					if( shapeObject is Shape)
					{
						Shape shape = (Shape)shapeObject;
						Point pos = this.SnapGridPoint(shape.Position , true);
						if( pos != shape.Position) {_shapePropPos.SetValue(shape,pos); commit = true;}
					}

				if( commit) tx.Commit();
				else tx.Cancel();
			}

			if( commit) this.Invalidate(false);
			
		}


		private void OnAlignLeft(object sender, EventArgs e)
		{
			AlignTopLeft( true);
		}

		private void OnAlignTop(object sender, EventArgs e)
		{
			AlignTopLeft( false );
		}

		private void OnAlignBottom(object sender, EventArgs e)
		{
			AlignRightBottom( false );
		}

		private void OnAlignRight(object sender, EventArgs e)
		{
			AlignRightBottom( true );
		}


		private void AlignCenters( bool horizontal)
		{
			ISelectionService ss = _rootDesigner.SelectionService;
			Shape primShape = ss.PrimarySelection as Shape;
			if( primShape == null || primShape == _rootDesigner.ShapeContainer) return;

			IList selectedShapes = (IList)ss.GetSelectedComponents();
			if( selectedShapes.Count == 0) return;
		
			Point primCenter = Point.Round( RectangleUtil.CenterPoint( primShape.Bounds ));

			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Align Shape"))
			{
				foreach( object shapeObject in selectedShapes )
					if( shapeObject is Shape && shapeObject != primShape )
					{
						Shape shape = (Shape)shapeObject;
						Point pos  = shape.Position;
						Point center = Point.Round( RectangleUtil.CenterPoint ( shape.Bounds ) );
						if( horizontal ) 
						{
							int dx = center.X - primCenter.X;
							pos.X -= dx;
						}
						else  
						{
							int dy = center.Y - primCenter.Y;
							pos.Y -= dy;
						}

						if( pos != shape.Position ) { _shapePropPos.SetValue(shape,pos); commit = true;}
					}

				if( commit ) tx.Commit();
				else tx.Cancel();
			}

			if( commit ) this.Invalidate(false);


		}

		private void OnAlignHorizontalCenters(object sender, EventArgs e)
		{
			AlignCenters( true );
		}


		private void OnAlignVerticalCenters(object sender, EventArgs e)
		{
			AlignCenters( false );
		}


		private void MakeSameSize(bool height, bool width)
		{
			if( !height && !width) return;

			ISelectionService ss = _rootDesigner.SelectionService;
			Shape primShape = ss.PrimarySelection as Shape;
			if( primShape == null || primShape == _rootDesigner.ShapeContainer) return;

			IList selectedShapes = (IList)ss.GetSelectedComponents();
			if( selectedShapes.Count == 0) return;
		
			Size primSize = primShape.Size;

			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Align Shape"))
			{
				foreach( object shapeObject in selectedShapes )
					if( shapeObject is Shape && shapeObject != primShape )
					{
						Shape shape = (Shape)shapeObject;
						Size size = shape.Size;

						if( height )size.Height = primSize.Height;	
						if( width ) size.Width = primSize.Width;	

						if( size != shape.Size ) { _shapePropSize.SetValue(shape,size); commit = true;}
					}

				if( commit ) tx.Commit();
				else tx.Cancel();
			}

			if( commit ) this.Invalidate(false);


		}

		private void OnSizeToControlHeight(object sender, EventArgs e)
		{
			//Make same height
			MakeSameSize( true, false );
		}

		private void OnSizeToControlWidth(object sender, EventArgs e)
		{
			//Make same width
			MakeSameSize( false, true );

		}

		private void OnSizeToControl(object sender, EventArgs e)
		{
			//Make same height and width
			MakeSameSize( true, true );

		}

		private void OnSizeToGrid(object sender, EventArgs e)
		{
			ISelectionService ss = _rootDesigner.SelectionService;
			Shape primShape = ss.PrimarySelection as Shape;
			if( primShape == null) return;

			IList selectedShapes = (IList)ss.GetSelectedComponents();
			if( selectedShapes.Count == 0) return;
			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Shapes moved"))
			{
				foreach( object shapeObject in selectedShapes ) 
					if( shapeObject is Shape)
					{
						Shape shape = (Shape)shapeObject;
						
						Point pos = this.SnapGridPoint(shape.Position , true);
						if( pos != shape.Position) {_shapePropPos.SetValue(shape,pos); commit = true;}
						
						Size size =  new Size(this.SnapGridPoint( new Point( shape.Size ), true ));
						
						if( size != shape.Size ) 
						{
							size.Width+= _gridSize.Width;
							size.Height+= _gridSize.Height;
							_shapePropSize.SetValue(shape,size); 
							commit = true;
						}
					}

				if( commit) tx.Commit();
				else tx.Cancel();
			}

			if( commit) this.Invalidate(false);

		}


		private void AlignToContainerCenter( bool horizontal )
		{
			ISelectionService ss = _rootDesigner.SelectionService;

			IList selectedShapes = (IList)ss.GetSelectedComponents();
			if( selectedShapes.Count == 0) return;
		
			Point primCenter = Point.Round( RectangleUtil.CenterPoint( _rootDesigner.ShapeContainer.Bounds ));

			bool commit = false;

			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Align Shape"))
			{
				foreach( object shapeObject in selectedShapes )
					if( shapeObject is Shape && shapeObject != _rootDesigner.ShapeContainer )
					{
						Shape shape = (Shape)shapeObject;
						Point pos  = shape.Position;
						Point center = Point.Round( RectangleUtil.CenterPoint ( shape.Bounds ) );
						if( horizontal ) 
						{
							int dx = center.X - primCenter.X;
							pos.X -= dx;
						}
						else  
						{
							int dy = center.Y - primCenter.Y;
							pos.Y -= dy;
						}

						if( pos != shape.Position ) { _shapePropPos.SetValue(shape,pos); commit = true;}
					}

				if( commit ) tx.Commit();
				else tx.Cancel();
			}

			if( commit ) this.Invalidate(false);


		}


		private void OnCenterHorizontally(object sender, EventArgs e)
		{
			AlignToContainerCenter( true );
		}

		private void OnCenterVertically(object sender, EventArgs e)
		{
			AlignToContainerCenter( false );
		}


		private class ShapePositionComparer : IComparer  
		{
			private bool _horizontal;
			public ShapePositionComparer( bool horizontal )
			{
				_horizontal = horizontal;
			}


			int IComparer.Compare( object obj1, object obj2 )  
			{
				Shape so1 = (Shape) obj1;
				Shape so2 = (Shape) obj2;
				Point p1= so1.Position;
				Point p2= so2.Position;

				if( _horizontal) 
				{
					//if( p1.X == p2.X ) return 0;
					if( p1.X == p2.X ) //if same location check width
					{
						Size s1 = so1.Size;
						Size s2 = so2.Size;
						if( s1.Width == s2.Width ) return 0;
						
						if(s2.Width > s1.Width ) return 1;
					}

					
					if( p2.X < p1.X ) return 1;

				}
				else 
				{
					//if( p1.Y == p2.Y ) return 0;
					if( p1.Y == p2.Y ) //if same location check height
					{
						Size s1 = so1.Size;
						Size s2 = so2.Size;
						if( s1.Height == s2.Height ) return 0;
						
						if(s2.Height> s1.Height ) return 1;
					}


					if( p2.Y < p1.Y ) return 1;
				}

				return -1;

			}
		}

		private ArrayList SortSelectedShapes( bool horizontal)
		{

			ArrayList shapes = new ArrayList();
			ISelectionService ss = _rootDesigner.SelectionService;

			IList selectedShapes = (IList)ss.GetSelectedComponents();
			if( selectedShapes.Count == 0) return shapes;
			
			foreach( object shape in selectedShapes )
				if( shape is Shape && shape != _rootDesigner.ShapeContainer )
					shapes.Add( shape );
			

			shapes.Sort( new ShapePositionComparer( horizontal ));	

			return shapes;

		}

		private void ConcatenateShapeSpaces( bool horizontal)
		{
			ArrayList shapes = SortSelectedShapes( horizontal );
			
			if( shapes.Count <= 1 ) return;

			bool commit = false;
			string txText = horizontal ? "Remove Horizontal Spacing":"Remove Vertical Spacing";
			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction(txText))
			{
				for( int i = 1; i < shapes.Count; i++)
				{
					Shape prev = shapes[i-1] as Shape;
					Shape next = shapes[i] as Shape;
					
					Rectangle	prevBounds	= Rectangle.Round( prev.Bounds );
					Point		nextPos		= next.Position;

					if( horizontal ) nextPos.X = prevBounds.Right;
					else nextPos.Y = prevBounds.Bottom;

					if( nextPos != next.Position)
					{
						_shapePropPos.SetValue(next,nextPos); 
						commit = true;
					}
				}

				if( commit ) tx.Commit();
				else tx.Cancel();
			}

			if( commit ) this.Invalidate(false);


		}

		private void OnHorizSpaceConcatenate(object sender, EventArgs e)
		{
			ConcatenateShapeSpaces( true );
		}

		private void OnVertSpaceConcatenate(object sender, EventArgs e)
		{
			ConcatenateShapeSpaces( false );
		}



		private void IncreaseShapeSpaces( bool horizontal )
		{
			ArrayList shapes = SortSelectedShapes( horizontal );
			
			if( shapes.Count <= 1 ) return;

			int offset = 1;
			if( _snapToGrid)
			{
				if( horizontal) offset = _gridSize.Width;
				else offset = _gridSize.Height;
			}

			int primIndex = 0;
			ISelectionService ss = _rootDesigner.SelectionService;
			for( int i = 0; i < shapes.Count; i++)
			{
				if( shapes[i] == ss.PrimarySelection)
				{ primIndex = i; break;}
			}

			string txText = horizontal ? "Increase Horizontal Spacing":"Increase Vertical Spacing";
			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction(txText))
			{
				for( int i = 0; i < shapes.Count; i++)
				{
					
					int factor = i - primIndex;
					if( factor == 0) continue;//=primary shape
					Shape shape = (Shape)shapes[i];

					Point pos = shape.Position;

					if( horizontal ) pos.X += factor * offset;
					else pos.Y+= factor * offset;
					
					_shapePropPos.SetValue(shape,pos); 

				}

				tx.Commit();
			}

			this.Invalidate(false);
 		}

		private void OnHorizSpaceIncrease(object sender, EventArgs e)
		{
			IncreaseShapeSpaces( true );
		}

		private void OnVertSpaceIncrease(object sender, EventArgs e)
		{
			IncreaseShapeSpaces( false );
		}

		private void DecreaseShapeSpaces( bool horizontal )
		{
			ArrayList shapes = SortSelectedShapes( horizontal );
			
			if( shapes.Count <= 1 ) return;

			int offset = 1;
			if( _snapToGrid)
			{
				if( horizontal) offset = _gridSize.Width;
				else offset = _gridSize.Height;
			}

			int primIndex = 0;
			ISelectionService ss = _rootDesigner.SelectionService;
			for( int i = 0; i < shapes.Count; i++)
			{
				if( shapes[i] == ss.PrimarySelection)
				{ primIndex = i; break;}
			}

			Shape primShape = (Shape)shapes[primIndex];
			Point primPos = primShape.Position;

			string txText = horizontal ? "Increase Horizontal Spacing":"Increase Vertical Spacing";
			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction(txText))
			{
				for( int i = 0; i < shapes.Count; i++)
				{
					
					int factor = i - primIndex;
					if( factor == 0) continue;//=primary shape
					Shape shape = (Shape)shapes[i];

					Point pos = shape.Position;

					if( horizontal ) 
					{
						pos.X -= factor * offset;
						if( (factor < 0 && pos.X > primPos.X) || (factor > 0 && pos.X < primPos.X) ) pos.X = primPos.X;

					}
					else 
					{
						pos.Y-= factor * offset;
						if( (factor < 0 && pos.Y > primPos.Y ) || (factor > 0 && pos.Y < primPos.Y) ) pos.Y = primPos.Y;
					}


					
					_shapePropPos.SetValue(shape,pos); 

				}

				tx.Commit();
			}

			this.Invalidate(false);
		}


		private void OnHorizSpaceDecrease(object sender, EventArgs e)
		{
			DecreaseShapeSpaces( true );
		}

		private void OnVertSpaceDecrease(object sender, EventArgs e)
		{
			DecreaseShapeSpaces( false );
		}

		private void MakeSpacesEqual( bool horizontal)
		{
			ArrayList shapes = SortSelectedShapes( horizontal );
			
			//if( shapes.Count <= 2 ) return;
			if( shapes.Count < 2 ) return;

			RectangleF ru= ((Shape)shapes[0]).Bounds;
			int width  = 0;
			int height = 0;

			foreach( Shape shape in shapes) 
			{
				ru = RectangleF.Union( ru, shape.Bounds);
				width  += shape.Size.Width;
				height += shape.Size.Height;
			}
			
			Rectangle union = Rectangle.Round( ru );

			int factorX = (union.Width  - width ) / ( shapes.Count - 1);
			int factorY = (union.Height - height) / ( shapes.Count - 1);

			bool commit = false;
			string txText = horizontal ? "Make Horizontal Spacing Equal":"Make Vertical Spacing Equal";
			using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction(txText))
			{
				for( int i = 1; i < shapes.Count; i++)
				{

					Shape prev = shapes[i-1] as Shape;
					Shape next = shapes[i] as Shape;

					Point pos = next.Position;

					Rectangle prevBounds = Rectangle.Round( prev.Bounds );
					if( horizontal ) 
					{
						pos.X = prevBounds.Right +  factorX;
						if( pos.X < prevBounds.Right) pos.X = prevBounds.Right;
					}
					else 
					{
						pos.Y = prevBounds.Bottom + factorY;
						if( pos.Y < prevBounds.Bottom) pos.Y = prevBounds.Bottom;
					}

					if( pos != next.Position)
					{
						_shapePropPos.SetValue(next,pos); 
						commit = true;
					}

				}

				if(commit) tx.Commit();
				else tx.Cancel();
			}

			this.Invalidate(false);


		}


		private void OnHorizSpaceMakeEqual(object sender, EventArgs e)
		{
			MakeSpacesEqual( true );
		}

		private void OnVertSpaceMakeEqual(object sender, EventArgs e)
		{
			MakeSpacesEqual( false );
		}


		#endregion MENU COMMAND SERVICE

		protected override void OnSizeChanged(EventArgs e)
		{
			
			RecalculateScrollSize();
			base.OnSizeChanged (e);
		}


		protected internal void RecalculateScrollSize(  )
		{

			try
			{
				if( _rootDesigner == null) return;

				IShapeContainerProvider scp = _rootDesigner.ShapeContainerProvider;

				Size scpSize = scp.Size;
				scpSize.Width +=20;
				scpSize.Height+=20;


				RectangleF union = new RectangleF( PointF.Empty, scpSize); 
				union = RectangleF.Union(union, _rootDesigner.ShapeContainer.Bounds );

				foreach( Shape shape in _rootDesigner.ShapeContainer.Shapes)
				{
					if( Adornment( shape ) != null)
						union = RectangleF.Union(union, Adornment(shape).InvalidatingBounds );
					else
						union = RectangleF.Union(union, shape.InvalidatingBounds );
				}


				SizeF scrollSize = this.ClientRectangle.Size;
				if( union.Bottom   > this.ClientRectangle.Height )  
					scrollSize.Height = union.Bottom ;
				if( union.Right    > this.ClientRectangle.Width )  	
					scrollSize.Width = union.Right ;



				this.AutoScrollMinSize = Size.Ceiling( scrollSize );

				InvalidateRulers();
			}
			catch( Exception e)
			{
				FileWatcher.WriteLine("RecalculateScrollSize failed!\n"+ e.StackTrace);
				throw e;
			}

		}



		private void ShapePathBoundsChanged( object sender, ValueChangeEventArgs e)
		{
			ResetRulerRanges();
			if( _dragDropData != null) return;
			Rectangle invBounds = Rectangle.Ceiling(RectangleF.Union( (RectangleF)e.OldValue, (RectangleF)e.NewValue ));
			InvalidateShapeBounds( invBounds );

			RecalculateScrollSize();


		}

		private void ShapeContainerPathBoundsChanged(object sender, ValueChangeEventArgs e)
		{
			if( sender == _rootDesigner.ShapeContainer ) ResetRulerRanges();
			
		}
		private void ShapeContainerBoundsChanged(object sender, ValueChangeEventArgs e)
		{
			if( sender == _rootDesigner.ShapeContainer ) RecalculateScrollSize();
			
		}


		private void ShapeInternalChanged(object sender, EventArgs e)
		{
			try
			{
                if (this._rootDesigner == null) return;
                IDesignerHost dh = _rootDesigner.DesignerHost;
                if (dh == null || dh.Loading) return;

				if(!( sender is Shape )) return;

				RecalculateScrollSize();

				Shape shape = (Shape)sender;
				ShapeAdornment a = Adornment(shape);

				if( a != null )	InvalidateShapeBounds( a.InvalidatingBounds );

			}
			catch( Exception exc )
			{
				FileWatcher.WriteLine("RulingPanel::ShapeInternalChanged failed :"+exc.Message);
			}

		}


		protected internal Point TransformPoint( Point clientPoint )
		{
			return new Point( clientPoint.X - AutoScrollPosition.X, clientPoint.Y - AutoScrollPosition.Y);
		}


		protected internal Point TransformPoint( Point clientPoint , bool snapToGrid )
		{
			clientPoint =  new Point( clientPoint.X - AutoScrollPosition.X, clientPoint.Y - AutoScrollPosition.Y);

			if( snapToGrid ) return SnapGridPoint( clientPoint );
			else return clientPoint;
		}


		protected internal Point SnapGridPoint( Point clientPoint )
		{
			return SnapGridPoint( clientPoint, _snapToGrid );
		}

		protected internal Point SnapGridPoint( Point clientPoint , bool snap )
		{
			if( snap )
			{
				clientPoint.X = _gridSize.Width * (clientPoint.X / _gridSize.Width) ;
				clientPoint.Y = _gridSize.Height * (clientPoint.Y / _gridSize.Height) ;
			}

			return clientPoint;
		}

		private Rectangle GetPointsBounds( params Point[] pts )
		{
			if( pts.Length < 2) return Rectangle.Empty;

			GraphicsPath path = new GraphicsPath();
			path.AddLines( pts );
			return Rectangle.Round( path.GetBounds());
		}

		protected internal Rectangle GetSelectedBounds()
		{
			if( _rootDesigner == null) return Rectangle.Empty;

			Rectangle rect = Rectangle.Empty;
			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss != null && ss.SelectionCount > 0 )
			{
				ICollection selectedComponents = ss.GetSelectedComponents();
				foreach( object shapeObject in selectedComponents ) 
					if( shapeObject is Shape )
					{
						Shape shape = (Shape)shapeObject;
						ShapeAdornment a =Adornment(shape);

						if( a == null) continue;

						rect = Rectangle.Union( rect, a.InvalidatingBounds);
					}
			}


			return rect;

		}
		


		protected internal void InvalidateShapes()
		{
			if( _rootDesigner == null) return;

			
			RectangleF union = Adornment(_rootDesigner.ShapeContainer).InvalidatingBounds;
			//New:23.06.06 -----------------------
			union.X += this.AutoScrollPosition.X;
			union.Y += this.AutoScrollPosition.Y;
			//-------------------------------------
			union.Inflate(_outlineWidth,_outlineWidth);
			Invalidate(Rectangle.Ceiling( union ), false);

		}

		protected internal void InvalidateSelectedBounds()
		{
			if( _rootDesigner == null) return;

			Rectangle rect = GetSelectedBounds();

			if( rect != Rectangle.Empty ) 
			{
				rect.X += this.AutoScrollPosition.X;
				rect.Y += this.AutoScrollPosition.Y;
				InvalidateShapeBounds( rect );
			}
			else Invalidate( this.ClientRectangle ,false);

		}

		protected internal void InvalidateShapeBounds( Rectangle bounds )
		{
			bounds.X += this.AutoScrollPosition.X;
			bounds.Y += this.AutoScrollPosition.Y;
			bounds.Inflate(_outlineWidth,_outlineWidth);
			this.Invalidate( bounds, false);
		}

		protected internal void InvalidateExact( Rectangle bounds )
		{
			bounds.X += this.AutoScrollPosition.X;
			bounds.Y += this.AutoScrollPosition.Y;
			bounds.Inflate(1,1);
			this.Invalidate( bounds, false );
		}

		protected internal Shape HitTest( Point pt, bool transform)
		{
			try
			{
				if( _rootDesigner == null) return null;
				
				if( transform) pt	= TransformPoint( pt );
				
				ShapeContainer shapeContainer = _rootDesigner.ShapeContainer;

				IList list = (IList)_rootDesigner.SelectionService.GetSelectedComponents();
				foreach( object shapeObject in list)
					if( shapeObject is Shape)
					{
						Shape shape = (Shape)shapeObject;
						if( shape.Site == null || shape == shapeContainer) continue;

						ShapeAdornment a = Adornment(shape);
						CursorStatus status = a.HitTest(pt);
						if ( status != CursorStatus.None) 
							return shape;
					}

				ShapeAdornment pa = Adornment(shapeContainer);
				CursorStatus pstatus = pa.HitTest(pt);
				if ( pstatus != CursorStatus.None) return shapeContainer;


				ShapeCollection shapes = _rootDesigner.ShapeContainer.Shapes;
				for( int i = shapes.Count-1; i>=0; i--)
				{
					Shape shape = shapes[i] as Shape;
					if( shape != null && 
						shape.Site != null &&
						shape.HitTest( pt))
						return shape;
				}

				if( shapeContainer.HitTest( pt)) return shapeContainer;

				return null;
			}
			catch( Exception exc)
			{
				//FileWatcher.WriteLine("Shape HitTest failed:"+ exc.Message);
				throw exc;
			}
		}

		protected CursorStatus GetCursorStatus( Point pt , out Shape shape )
		{
			return GetCursorStatus(pt,true, out shape);
		}

		protected CursorStatus GetCursorStatus( Point pt, bool transform, out Shape outShape  )
		{
			try
			{
				outShape = null;

				if( _rootDesigner == null) return CursorStatus.None;


				ISelectionService ss = _rootDesigner.SelectionService;
				
				if( ss == null) return CursorStatus.None;
				

				if( transform ) pt	= TransformPoint( pt );

				ShapeContainer shapeContainer = _rootDesigner.ShapeContainer;


				IList list = (IList)ss.GetSelectedComponents();

				
				foreach( object shapeObject in list)
					if( shapeObject is Shape)
					{
						Shape shape = (Shape)shapeObject;
						if( shape.Site == null || shape == shapeContainer ) continue;

						ShapeAdornment a = Adornment(shape);
						CursorStatus status = a.HitTest(pt);
						if ( status != CursorStatus.None) 
						{		outShape = shape;
								return status;
						}
					}

				if( ss.PrimarySelection == _rootDesigner.ShapeContainer)//New if: 16.07.06
				{
					ShapeAdornment pa = Adornment(shapeContainer);
                    CursorStatus pstatus = pa.HitTest(pt);
                    if (pstatus != CursorStatus.None)
                    {
                        outShape = shapeContainer;
                        return pstatus;
                    }
				}
				
				ShapeCollection shapes = _rootDesigner.ShapeContainer.Shapes;
				for( int i = shapes.Count-1; i>=0; i--)
				{
					Shape shape = shapes[i] as Shape;
					if( shape != null && 
						shape.Site!= null && 
						shape.HitTest(pt))
					{
						outShape = shape;
						return CursorStatus.MouseOver;
					}
				}

				if( shapeContainer.HitTest( pt )) 
				{		outShape = shapeContainer;
						return CursorStatus.MouseOver;
				}

				return CursorStatus.None;

			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("GetCursorStatus failed:"+ exc.Message);
                FileWatcher.WriteLine(exc.StackTrace);
                throw exc;
			}

		}


		#region MOUSE DRAG & DROP DATA

		DragDropData			_dragDropData					= null;
		Hashtable				_dragShapeAttributes		= null;// Contains Shape Attributes

		#endregion MOUSE DRAG & DROP DATA

		#region MOUSE MOVE OPERATIONS

		private void OnWarpShapes( Point offset )
		{
			if( _rootDesigner == null) return;
			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss == null || ss.SelectionCount == 0 ) return;

			//Point ptCurrent		= _dragDropData.CurrentMousePosition;
			Rectangle oldRect	= Rectangle.Empty;
			Rectangle newRect	= Rectangle.Empty;

			Shape primaryShape = _dragDropData.PrimaryAttributes.Shape;
			CursorStatus cursorStatus = _dragDropData.CursorStatus;
			
			int rem = int.MaxValue; 
			Math.DivRem( primaryShape.Rotation, 360, out rem ); 
			if( rem != 0 && primaryShape != _rootDesigner.ShapeContainer)
			{
				Matrix m = new Matrix();
				PointF anchor =primaryShape.GetRotatingPoint();
				m.RotateAt(-primaryShape.Rotation, anchor, MatrixOrder.Append);

				Point[] offsetVector = new Point[]{ offset};
				m.TransformVectors( offsetVector );
				offset = offsetVector[0];
			}


			ICollection selectedComponents = ss.GetSelectedComponents();
			foreach( object shapeObject in selectedComponents ) 
				if( shapeObject is Shape )
				{
					Shape shape = (Shape)shapeObject;
					ShapeAdornment a = Adornment(shape);
					Point topLeft		= shape.Warp.TopLeft;
					Point topRight		= shape.Warp.TopRight;
					Point bottomLeft	= shape.Warp.BottomLeft;
					Point bottomRight	= shape.Warp.BottomRight;

					oldRect = Rectangle.Union( oldRect, Rectangle.Ceiling( a.InvalidatingBounds));
				

					if( cursorStatus == CursorStatus.WarpTopLeft)
					{
						topLeft.X += offset.X;
						topLeft.Y += offset.Y;
					}

					if( cursorStatus == CursorStatus.WarpTopRight)
					{
						topRight.X += offset.X;
						topRight.Y += offset.Y;
					}
					if( cursorStatus == CursorStatus.WarpBottomLeft)
					{
						bottomLeft.X += offset.X;
						bottomLeft.Y += offset.Y;
					}
					if( cursorStatus == CursorStatus.WarpBottomRight)
					{
						bottomRight.X += offset.X;
						bottomRight.Y += offset.Y;
					}

					//------------------------------------------
					if( cursorStatus == CursorStatus.WarpTop)
					{
						topLeft.Y += offset.Y;
						topLeft.X += offset.X;

						topRight.Y += offset.Y;
						topRight.X += offset.X;
					}
					if( cursorStatus == CursorStatus.WarpBottom)
					{
						bottomRight.Y += offset.Y;
						bottomRight.X += offset.X;

						bottomLeft.Y += offset.Y;
						bottomLeft.X += offset.X;
					}

					if( cursorStatus == CursorStatus.WarpRight)
					{
						topRight.X		+= offset.X;
						topRight.Y		+= offset.Y;

						bottomRight.X	+= offset.X;
						bottomRight.Y	+= offset.Y;
					}
					if( cursorStatus == CursorStatus.WarpLeft)
					{
						bottomLeft.X += offset.X;
						bottomLeft.Y += offset.Y;

						topLeft.X += offset.X;
						topLeft.Y += offset.Y;
					}

					shape.Warp = new Warp( topLeft, topRight,bottomLeft, bottomRight, shape.Warp.WarpMode);
					newRect = Rectangle.Union( newRect, Rectangle.Ceiling(a.InvalidatingBounds));
				}

			if( primaryShape == _rootDesigner.ShapeContainer)
				InvalidateShapes();
			else
			{
				Rectangle union = Rectangle.Union( oldRect, newRect);
				if( union != Rectangle.Empty ) InvalidateShapeBounds( union );
			}

		}

		private void OnScaleShapes( Point offset )
		{
			if( _rootDesigner == null) return;
			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss == null || ss.SelectionCount == 0 ) return;

			ICollection selectedComponents = ss.GetSelectedComponents();
			Shape primaryShape	= _dragDropData.PrimaryAttributes.Shape;
			Rectangle oldRect	= Rectangle.Empty;
			Rectangle newRect	= Rectangle.Empty;


			//PointF ptCurrent			= _dragDropData.CurrentMousePosition;
			RectangleF pb				= primaryShape.GetPathBounds();		
			CursorStatus cursorStatus	= _dragDropData.CursorStatus;

			if( primaryShape.Scale.AppendRotate == false)
			{
				int rem = int.MaxValue; 
				Math.DivRem( primaryShape.Rotation, 360, out rem ); 
				if( rem != 0 && primaryShape != _rootDesigner.ShapeContainer)
				{
					Matrix m = new Matrix();
					PointF anchor = primaryShape.GetRotatingPoint();
					m.RotateAt(-primaryShape.Rotation, anchor, MatrixOrder.Append);

					Point[] offsetVector = new Point[]{ offset};
					m.TransformVectors( offsetVector );
					offset = offsetVector[0];
				}
			}


			switch( cursorStatus )
			{
				case CursorStatus.ScaleLeft:
					offset.X	= -offset.X; 
					offset.Y	= 0;
					break;
				case CursorStatus.ScaleRight:
					offset.Y	= 0;
					break;
				case CursorStatus.ScaleTop:
					offset.Y	= -offset.Y;
					offset.X	= 0; 
					break;
				case CursorStatus.ScaleBottom:
					offset.X	= 0;
					break;
				default:return;
			}
			
			foreach( object shapeObject in selectedComponents ) 
				if( shapeObject is Shape )
				{
					Shape shape = (Shape)shapeObject;

					ShapeAdornment a	= Adornment(shape);
					oldRect = Rectangle.Union( oldRect, a.InvalidatingBounds );
					
					shape.AddScale( offset.X, offset.Y );
					newRect = Rectangle.Union( newRect, a.InvalidatingBounds );
			
				}

			if( primaryShape == _rootDesigner.ShapeContainer)
				InvalidateShapes();
			else
			{
				Rectangle union = Rectangle.Union( oldRect, newRect);
				if( union != Rectangle.Empty ) InvalidateShapeBounds( union );
			}

		}


		private void OnEditPoints(Point offset)
		{
			if( _rootDesigner == null) return;
		

			VectorShape primaryShape = _dragDropData.PrimaryAttributes.Shape as VectorShape;
			if( primaryShape == null) return;
			ShapeAdornment a = Adornment( primaryShape );
			int editingIndices = a.EditingPointIndices;
			if( editingIndices == -1) return;

			Point ptCurrent		= _dragDropData.CurrentMousePosition;

			a.BeginEditPoint( ptCurrent );

			int rem = int.MaxValue; 
			Math.DivRem( primaryShape.Rotation, 360, out rem ); 
			if( rem != 0 )
			{
				Matrix m = new Matrix();
				PointF anchor = primaryShape.GetRotatingPoint();
				m.RotateAt(-primaryShape.Rotation, anchor, MatrixOrder.Append);

				Point[] transCurrent = new Point[]{ ptCurrent};
				m.TransformPoints( transCurrent );
				ptCurrent = transCurrent[0];

			}
	

			AnchorPoint[] controlPoints = primaryShape.Points;
			AnchorPoint ptEditing = controlPoints[ editingIndices];
			ptEditing.Point = ptCurrent;
			controlPoints[editingIndices] = ptEditing;
			primaryShape.Points =  controlPoints;

			InvalidateShapeBounds( a.InvalidatingBounds );

		}

		private void OnEditControlPoints(Point offset)
		{
			if( _rootDesigner == null) return;
		

			Shape primaryShape = _dragDropData.PrimaryAttributes.Shape;
			ShapeAdornment a = Adornment( primaryShape );
			int editingIndices = a.EditingControlPointIndices;
			if( editingIndices == -1) return;

			Point ptCurrent		= _dragDropData.CurrentMousePosition;

			a.BeginEditControlPoint( ptCurrent );


			int rem = int.MaxValue; 
			Math.DivRem( primaryShape.Rotation, 360, out rem ); 
			if( rem != 0 && primaryShape != _rootDesigner.ShapeContainer)
			{
				Matrix m = new Matrix();
				PointF anchor = primaryShape.GetRotatingPoint();
				m.RotateAt(-primaryShape.Rotation, anchor, MatrixOrder.Append);

				Point[] transCurrent = new Point[]{ ptCurrent};
				m.TransformPoints( transCurrent );
				ptCurrent = transCurrent[0];

			}
	

			PointF[] controlPoints = primaryShape.ControlPoints;
			PointF ptEditing = controlPoints[ editingIndices];

			ptEditing = ptCurrent;
			controlPoints[ editingIndices] = ptEditing;
			primaryShape.ControlPoints =  controlPoints;

			InvalidateShapeBounds( a.InvalidatingBounds );

		}

		private void OnResizeShapes( Point offset )
		{
			if( _rootDesigner == null) return;
			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss == null || ss.SelectionCount == 0 ) return;

			Point ptCurrent		= _dragDropData.CurrentMousePosition;
			Rectangle oldRect	= Rectangle.Empty;
			Rectangle newRect	= Rectangle.Empty;

			Shape primaryShape = _dragDropData.PrimaryAttributes.Shape;
			CursorStatus cursorStatus = _dragDropData.CursorStatus;
			
			int rem = int.MaxValue; 
			Math.DivRem( primaryShape.Rotation, 360, out rem ); 
			if( rem != 0 && primaryShape != _rootDesigner.ShapeContainer)
			{
				Matrix m = new Matrix();
				PointF anchor = primaryShape.GetRotatingPoint();
				m.RotateAt(-primaryShape.Rotation, anchor, MatrixOrder.Append);

				Point[] offsetVector = new Point[]{ offset};
				m.TransformVectors( offsetVector );
				offset = offsetVector[0];

				Point[] transCurrent = new Point[]{ ptCurrent};
				m.TransformPoints( transCurrent );
				ptCurrent = transCurrent[0];
			}
			

			ICollection selectedComponents = ss.GetSelectedComponents();
			foreach( object shapeObject in selectedComponents ) 
			{
				if(!( shapeObject is Shape )) continue;

				Shape shape = (Shape)shapeObject;
				ShapeAdornment a = Adornment(shape);

				Size minSize = shape.MinSize;
				oldRect = Rectangle.Union( oldRect, a.InvalidatingBounds);

				RectangleF shapeBounds = shape.Bounds;
				if( cursorStatus == CursorStatus.Right || 
					cursorStatus == CursorStatus.BottomRight ||
					cursorStatus == CursorStatus.TopRight)
					if( offset.X != 0 )
						if( primaryShape.Bounds.Width > primaryShape.MinSize.Width ||  ptCurrent.X > primaryShape.Bounds.Right)
						{
							SizeF size	= shapeBounds.Size ;
							size.Width += offset.X;
							size.Width = size.Width < minSize.Width ? minSize.Width : size.Width;

							shapeBounds.Size = size;
						}



				if( cursorStatus == CursorStatus.Bottom|| 
					cursorStatus == CursorStatus.BottomRight ||
					cursorStatus == CursorStatus.BottomLeft)//Location fixed:OK
					if( offset.Y != 0 )
						if( primaryShape.Size.Height > primaryShape.MinSize.Height ||  ptCurrent.Y >= primaryShape.Bounds.Bottom)
						{
							SizeF size	= shapeBounds.Size;
							size.Height += offset.Y;
							size.Height = size.Height < minSize.Height ? minSize.Height : size.Height;
						
							shapeBounds.Size = size;

						}

				if( cursorStatus == CursorStatus.Top|| 
					cursorStatus == CursorStatus.TopLeft ||
					cursorStatus == CursorStatus.TopRight) // Bottom fixes
					if( offset.Y != 0 )
						if( primaryShape.Size.Height > primaryShape.MinSize.Height ||  ptCurrent.Y <= primaryShape.Bounds.Top)
						{
							RectangleF currentBounds = shapeBounds;
							SizeF size	= shapeBounds.Size ;
							size.Height -= offset.Y;
							size.Height = size.Height < minSize.Height ? minSize.Height : size.Height;
						
							shapeBounds.Size = size;

							PointF position = shapeBounds.Location;
							position.Y += offset.Y;

							if( position.Y + size.Height > currentBounds.Bottom )
								position.Y = currentBounds.Bottom - minSize.Height;

							shapeBounds.Location = position;

						}

				if( cursorStatus == CursorStatus.Left|| 
					cursorStatus == CursorStatus.TopLeft ||
					cursorStatus == CursorStatus.BottomLeft)//Right fixed
					if( offset.X != 0 )
						if( primaryShape.Size.Width > primaryShape.MinSize.Width ||  ptCurrent.X <= primaryShape.Position.X )
						{
							SizeF size	= shapeBounds.Size;
							size.Width -= offset.X;
							size.Width = size.Width < minSize.Width ? minSize.Width : size.Width;

							shapeBounds.Size = size;

							PointF position = shapeBounds.Location;// shape.Position;
							position.X += offset.X;

							shapeBounds.Location = position;

						}

				if( shape.Bounds != shapeBounds)
				{
					shape.Bounds = shapeBounds;	
					//Add to update region
					newRect = Rectangle.Union( newRect, a.InvalidatingBounds );
				}
				


			}

			if( primaryShape == _rootDesigner.ShapeContainer)
				InvalidateShapes();
			else
			{
				Rectangle union = Rectangle.Union( oldRect, newRect);
				if( union != Rectangle.Empty ) InvalidateShapeBounds( union );
			}


		}
		
		private void OnMoveShapes( Point offset )
		{
			if( _rootDesigner == null) return;
			Point ptCurrent = _dragDropData.CurrentMousePosition;

			Rectangle oldRect = Rectangle.Empty;
			Rectangle newRect = Rectangle.Empty;


			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss == null || ss.SelectionCount == 0 ) return;

			Shape primaryShape = _dragDropData.PrimaryAttributes.Shape;

			ICollection selectedComponents = ss.GetSelectedComponents();
			foreach( object shapeObject in selectedComponents ) 
				if( shapeObject is Shape )
				{
					Shape shape = (Shape)shapeObject;
					ShapeAdornment a = Adornment(shape);
                    //if (a == null) continue;
					oldRect = Rectangle.Union( oldRect, a.InvalidatingBounds);
					
					if( shape != _rootDesigner.ShapeContainer)
					{
						
						Point position = shape.Position;
						Point oldPosition = position;
						position.Offset( offset.X, offset.Y );

						if( shape.Position != position )
						{
							shape.Position = position;
							newRect = Rectangle.Union( newRect, a.InvalidatingBounds );
						}
					}

				}
			
			Rectangle union = Rectangle.Union( oldRect, newRect);
			if( union != Rectangle.Empty ) InvalidateShapeBounds( union );

		}

		private float GetAngle( PointF rotatingPoint, PointF anchorPoint )
		{
			//Recalculate radius
			//------------------------------------------------
			PointF pt = new PointF (rotatingPoint.X - anchorPoint.X , rotatingPoint.Y  - anchorPoint.Y  ); 
			double radian = Math.Atan2( pt.Y, pt.X );
			double angle = radian * (180.0/Math.PI);
			return (float)(angle);
		}


		private void OnShearShapes( Point offset )
		{
			if( _rootDesigner == null) return;
			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss == null || ss.SelectionCount == 0 ) return;

			Rectangle oldRect	= Rectangle.Empty;
			Rectangle newRect	= Rectangle.Empty;

			Shape primaryShape	= _dragDropData.PrimaryAttributes.Shape;
			Point ptCurrent		= _dragDropData.CurrentMousePosition;
			bool shearX			= _dragDropData.CursorStatus == CursorStatus.ShearX;

			ICollection selectedComponents = ss.GetSelectedComponents();

			//Calculate shear
			//-------------------------------------------------------------------------------------------
			RectangleF pathBounds	 = primaryShape.GetBasePathBounds();
			Shear shear = primaryShape.Shear;

			if( shear.AppendRotate )
			{
				Matrix m = new Matrix();
				m.RotateAt(primaryShape.Rotation, primaryShape.GetRotatingPoint(), MatrixOrder.Append);
				using(GraphicsPath path = primaryShape.CloneBasePath())
				{
					path.Transform( m );
					pathBounds = path.GetBounds();
				}
			}
			else if( primaryShape.Rotation != 0 && primaryShape != _rootDesigner.ShapeContainer)
			{
				Matrix m = new Matrix();
				PointF anchor = primaryShape.GetRotatingPoint();
				m.RotateAt(-primaryShape.Rotation, anchor, MatrixOrder.Append);

				Point[] transCurrent = new Point[]{ ptCurrent };
				m.TransformPoints( transCurrent );
				ptCurrent = transCurrent[0];
			
			}
			
			PointF center = RectangleUtil.CenterPoint( pathBounds );
			// y = ( n * x ) + b,  
			// x = ( y - b ) / n, 
			// n = ( y1 - y2 ) / ( x1 - x2 ) 
			// b = y2 - ( n * x2 ) = y1 - ( n * x1 )
			
			float n = (center.Y - ptCurrent.Y)/( center.X - ptCurrent.X  );
			float b = ( ptCurrent.Y - ( n * ptCurrent.X));

			PointF ptis = PointF.Empty;
			Shear newShear = shear;


			if( shearX )
			{
				try
				{
					ptis.Y		= pathBounds.Bottom; 
					ptis.X		= ( ptis.Y - b )/n;
					newShear.X	= Convert.ToInt32( System.Math.Round(ptis.X - center.X ));
				}
				catch//(OverflowException ex)
				{
					//TODO : Handle OverflowException
					newShear.X  = 0;
				}
			}
			else
			{
				try
				{
					ptis.X		= pathBounds.Left;
					ptis.Y		= (n*ptis.X) + b;
					newShear.Y	= Convert.ToInt32( System.Math.Round(center.Y - ptis.Y));
				}
				catch//(OverflowException ex)
				{
					//TODO : Handle OverflowException
					newShear.Y =0;
				}
			}

			//FileWatcher.WriteLine( "SchnittPunkt: " + ptis.ToString());
			//-------------------------------------------------------------------------------------------

			Shear shearOffset = new Shear( newShear.X - shear.X ,newShear.Y - shear.Y ); //new

			if( shearOffset.X != 0 || shearOffset.Y != 0)//new
			foreach( object shapeObject in selectedComponents ) 
				if( shapeObject is Shape )
				{
					Shape shape = (Shape)shapeObject;

					ShapeAdornment a	= Adornment(shape);
					oldRect = Rectangle.Union( oldRect, a.InvalidatingBounds );


					if( shape == primaryShape)
						a.BeginShearing( _dragDropData.CurrentMousePosition, shearX );

					Shear oldShear = shape.Shear;//new
					oldShear.X	+=  shearOffset.X;
					oldShear.Y	+=  shearOffset.Y;
					shape.Shear = oldShear;// newShear; //new

					newRect = Rectangle.Union( newRect, a.InvalidatingBounds );
			
				}

			if( primaryShape == _rootDesigner.ShapeContainer)
				InvalidateShapes();
			else
			{
				Rectangle union = Rectangle.Union( oldRect, newRect);
				if( union != Rectangle.Empty ) InvalidateShapeBounds( union );
			}
		}

		private void OnRotateShapes( )
		{
			if( _rootDesigner == null) return;
			ISelectionService ss = _rootDesigner.SelectionService;
			if( ss == null || ss.SelectionCount == 0 ) return;

			Rectangle oldRect	= Rectangle.Empty;
			Rectangle newRect	= Rectangle.Empty;

			Point ptCurrent				= _dragDropData.CurrentMousePosition;
			Shape primaryShape			= _dragDropData.PrimaryAttributes.Shape;
			Point anchorPoint			= Point.Round(_dragDropData.RotationAnchor);

			int beginRotate				= primaryShape.Rotation;
			int endRotate				= primaryShape.GetRotatingAngle( ptCurrent );
			int delta					= endRotate - beginRotate;

			ICollection selectedComponents = ss.GetSelectedComponents();
			foreach( object shapeObject in selectedComponents ) 
				if( shapeObject is Shape )
				{
					Shape shape = (Shape)shapeObject;

					ShapeAdornment a	= Adornment(shape);
					oldRect = Rectangle.Union( oldRect, a.InvalidatingBounds );

					if( selectedComponents.Count == 1)
						shape.Rotation += delta;
						//----------------------------------------------------------------
					else
						shape.AddRotation( delta ,anchorPoint);
					//----------------------------------------------------------------

					if( shape == primaryShape) a.BeginRotation( ptCurrent );

					newRect = Rectangle.Union( newRect, a.InvalidatingBounds );
			
				}

			if( primaryShape == _rootDesigner.ShapeContainer)
				InvalidateShapes();
			else
			{
				Rectangle union = Rectangle.Union( oldRect, newRect);
				if( union != Rectangle.Empty ) InvalidateShapeBounds( union );
			}

		}


		#endregion MOUSE MOVE OPERATIONS

		#region MOUSE-UP COMMITS

		private void CommitWarp()
		{
			//FileWatcher.WriteLine("CommitWarp called");

			if (_dragDropData == null) return;

			ISelectionService ss = _rootDesigner.SelectionService;
			ICollection selectedComponents = ss.GetSelectedComponents();

			PropertyDescriptor	propWarp	 = TypeDescriptor.GetProperties(typeof( Shape ))["Warp"];
					
			Warp startWarp	= _dragDropData.PrimaryAttributes.Warp;
			Warp endWarp	= _dragDropData.PrimaryAttributes.Shape.Warp;

			if( !startWarp.Equals( endWarp ))
				using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Shapes warped"))
				{

					foreach( object shapeObject in selectedComponents ) 
						if( shapeObject is Shape)
						{
							Shape shape = (Shape)shapeObject;
							ShapeAttributes att = (ShapeAttributes)_dragShapeAttributes[shape];

							Warp newWarp= shape.Warp;
							shape.Warp = att.Warp;// Set Old scale;
							propWarp.SetValue(shape,newWarp);//Set new scale
						}

					tx.Commit();
				}

			CommitDragShapeAttributes();


		}

		private void CommitScale()
		{
			//FileWatcher.WriteLine("CommitScale called");

			if (_dragDropData == null) return;

			ISelectionService ss = _rootDesigner.SelectionService;
			ICollection selectedComponents = ss.GetSelectedComponents();

			PropertyDescriptor	propScale	 = TypeDescriptor.GetProperties(typeof( Shape ))["Scale"];
			Scale startScale	= _dragDropData.PrimaryAttributes.Scale;
			Scale endScale		= _dragDropData.PrimaryAttributes.Shape.Scale;

			if( !startScale.Equals( endScale ))
				using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Shapes scaled"))
				{

					foreach( object shapeObject in selectedComponents ) 
						if( shapeObject is Shape)
						{
							Shape shape = (Shape)shapeObject;
							ShapeAttributes att = (ShapeAttributes)_dragShapeAttributes[shape];

							Scale newScale= shape.Scale;
							shape.Scale = att.Scale;// Set Old scale;
							propScale.SetValue(shape,newScale);//Set new scale
						}

					tx.Commit();
				}

			CommitDragShapeAttributes();

		}


		private void CommitDragShapeAttributes()
		{
			RecalculateScrollSize();
			Invalidate( false );

			if( _dragShapeAttributes != null) _dragShapeAttributes.Clear();
			
			_dragShapeAttributes = null;
			_dragDropData = null;
		}
		
		private void EscapeCommit()
		{
			//Reset any changed being made in the designer...
			IDictionaryEnumerator shapeEnum = _dragShapeAttributes.GetEnumerator();
			while( shapeEnum.MoveNext())
			{	
				Shape shape			= (Shape)shapeEnum.Key;
				ShapeAttributes a	= (ShapeAttributes) shapeEnum.Value;
				shape.Bounds		= a.Bounds;
				shape.Scale			= a.Scale;
				shape.Rotation		= a.Rotation;
				shape.Shear			= a.Shear;
				shape.Warp			= a.Warp;
			}

			if( _dragDropData.CursorStatus == CursorStatus.Rotation )
			{
				Shape primShape = _dragDropData.PrimaryAttributes.Shape;
				ShapeAdornment a = Adornment(primShape);
				if( a != null ) a.EndRotation();
				if( a != null ) a.EndShearing();

			}

			CommitDragShapeAttributes();
		}

		private void CommitResize()
		{
			//FileWatcher.WriteLine("CommitResize called");

			if (_dragDropData == null) return;


			ISelectionService ss = _rootDesigner.SelectionService;
			ICollection selectedComponents = ss.GetSelectedComponents();

			RectangleF lastBounds		= _dragDropData.PrimaryAttributes.Bounds;
			RectangleF currentbounds	= _dragDropData.PrimaryAttributes.Shape.Bounds;



			if( lastBounds != currentbounds)
			{
				DesignerTransaction tx = tx = _rootDesigner.DesignerHost.CreateTransaction("Shape moved");

				try
				{
					//Reset the changed bounds
					if( _dragDropData.PrimaryAttributes.Shape != _rootDesigner.ShapeContainer)
					{
						if( _dragDropData.Effect == DragDropData.DragEffect.Resize	)
							foreach( Shape shape in _rootDesigner.ShapeContainer.Shapes)
								shape.UnlockRotation();
					}


					PropertyDescriptor	propPos	 = TypeDescriptor.GetProperties(typeof( Shape ))["Position"];
					PropertyDescriptor	propSize = TypeDescriptor.GetProperties(typeof( Shape ))["Size"];
					PropertyDescriptor	propAnchorPoints = TypeDescriptor.GetProperties(typeof( VectorShape ))["Points"];

					Shape primShape = _dragDropData.PrimaryAttributes.Shape;
			
					foreach( object shapeObject in selectedComponents ) 
						if( shapeObject is Shape)
						{
							Shape shape = (Shape)shapeObject;

							Rectangle newBounds = Rectangle.Round( shape.Bounds );

							ShapeAttributes att = (ShapeAttributes)_dragShapeAttributes[shape];
							Rectangle oldBounds = Rectangle.Round( att.Bounds );

							if( oldBounds == newBounds ) continue;
							
							shape.Bounds = oldBounds;
							if( newBounds.Location != oldBounds.Location)
								propPos.SetValue(shape,newBounds.Location);
							if( newBounds.Size != oldBounds.Size)
								propSize.SetValue(shape,newBounds.Size);

//							if( shape is VectorShape )
//							{
//								VectorShape vs = (VectorShape)shape;
//								AnchorPoint[] newAnchorPoints = vs.Points;
//								vs.Points = att.Points;
//								propAnchorPoints.SetValue( vs,newAnchorPoints );
//							}


						}



//					foreach( Shape shape in _rootDesigner.ShapeContainer.Shapes) 
//						if( shape.Site != null && !ss.GetComponentSelected( shape) )
//						{
//							Rectangle newBounds = Rectangle.Round( shape.Bounds );
//
//							ShapeAttributes att = (ShapeAttributes)_dragShapeAttributes[shape];
//							Rectangle oldBounds = Rectangle.Round( att.Bounds );
//
//							if( oldBounds == newBounds ) continue;
//
//							shape.Bounds = oldBounds;
//							if( newBounds.Location != shape.Position)
//								propPos.SetValue(shape,newBounds.Location);
//							if( newBounds.Size != shape.Size)
//								propSize.SetValue(shape,newBounds.Size);
//
//							if( shape is VectorShape)
//							{
//								VectorShape vs = (VectorShape)shape;
//								AnchorPoint[] newAnchorPoints = vs.Points;
//								vs.Points = att.Points;
//								propAnchorPoints.SetValue( vs,newAnchorPoints );
//							}
//						}

					if( tx != null) tx.Commit();

				}
				catch
				{
					if( tx != null) tx.Cancel();
					throw;
				}
			}

			CommitDragShapeAttributes();
			
		}

		private void CommitShear()
		{
			//FileWatcher.WriteLine("CommitShear called");

			if (_dragDropData == null) return;

			ISelectionService ss = _rootDesigner.SelectionService;
			ICollection selectedComponents = ss.GetSelectedComponents();

			PropertyDescriptor	propShear	 = TypeDescriptor.GetProperties(typeof( Shape ))["Shear"];
			Shear startShear	= _dragDropData.PrimaryAttributes.Shear;
			Shear endShear		= _dragDropData.PrimaryAttributes.Shape.Shear;

			if( !startShear.Equals( endShear ))
				using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Shapes sheared"))
				{
					foreach( object shapeObject in selectedComponents ) 
						if( shapeObject is Shape)
						{
							Shape shape = (Shape)shapeObject;
							ShapeAttributes att = (ShapeAttributes)_dragShapeAttributes[shape];

							Shear newShear= shape.Shear;
							shape.Shear = att.Shear;// Set Old scale;
							propShear.SetValue(shape,newShear);//Set new scale
						}

					tx.Commit();
				}

			Shape primShape = _dragDropData.PrimaryAttributes.Shape;
			ShapeAdornment a = Adornment( primShape );
			if( a != null ) a.EndShearing();

			CommitDragShapeAttributes();

		}

		private void CommitRotate()
		{
			try
			{
				//FileWatcher.WriteLine("CommitRotate called");

				if (_dragDropData == null) return;

				ISelectionService ss = _rootDesigner.SelectionService;
				ICollection selectedComponents = ss.GetSelectedComponents();

				PropertyDescriptor	propRotate		= TypeDescriptor.GetProperties(typeof( Shape ))["Rotation"];
				PropertyDescriptor	propPos			= TypeDescriptor.GetProperties(typeof( Shape ))["Position"];
					
				int startRotate		= _dragDropData.PrimaryAttributes.Rotation;
				int endRotate		= _dragDropData.PrimaryAttributes.Shape.Rotation;

				if( startRotate != endRotate)
				{

					//---------------------------------------------------------------------------------------
					foreach( Shape shape in _rootDesigner.ShapeContainer.Shapes) shape.UnlockRotation();
					//--------------------------------------------------------------------------------------

					using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Rotation"))
					{
						//Commit Move
						foreach( object shapeObject in selectedComponents ) 
							if( shapeObject is Shape)
							{
								Shape shape = (Shape)shapeObject;

								Rectangle newBounds = Rectangle.Round( shape.Bounds );
								ShapeAttributes att = (ShapeAttributes)_dragShapeAttributes[shape];
								Rectangle oldBounds = Rectangle.Round( att.Bounds );
								if( oldBounds.Location == newBounds.Location ) continue;

								shape.Bounds = oldBounds;
								propPos.SetValue(shape,newBounds.Location);
							}

						//----------------------------------------------------------------
						//Commit Rotate
						foreach( object shapeObject in selectedComponents ) 
							if( shapeObject is Shape)
							{
								Shape shape = (Shape)shapeObject;
								ShapeAttributes att = (ShapeAttributes)_dragShapeAttributes[shape];
								if( att.Rotation == shape.Rotation) continue;

								int newRotation= shape.Rotation;
								shape.Rotation = att.Rotation;// Set Old rotation;
								propRotate.SetValue(shape,newRotation);

							}
						tx.Commit();
					}
				}

				//End Rotations-----------------------------------
				foreach( object shapeObject in selectedComponents ) 
					if( shapeObject is Shape)
					{
						Shape shape = (Shape)shapeObject;
						ShapeAdornment a = Adornment( shape );
						if( a != null ) a.EndRotation();
					}

				CommitDragShapeAttributes();

			}
			catch( Exception e )
			{
				FileWatcher.WriteLine("Commiting rotation failed:"+e.Message);
			}
		}


		private void CommitEditControlPoints()
		{
			if (_dragDropData == null) return;

			Shape primaryShape = _dragDropData.PrimaryAttributes.Shape;
			ShapeAdornment a = Adornment( primaryShape );
			int editingIndices = a.EditingControlPointIndices;
			//FileWatcher.WriteLine( "CommitEditControlPoints::EditingControlPointIndices:" + editingIndices.ToString());

			if( editingIndices == -1) return;

			PointF[] newCtrlPoints = primaryShape.ControlPoints;
			PointF[] oldCtrlPoints = _dragDropData.PrimaryAttributes.ControlPoints;
			if( oldCtrlPoints[ editingIndices] != newCtrlPoints[ editingIndices]) 
			{
				PropertyDescriptor	propControlPoints		= TypeDescriptor.GetProperties(typeof( Shape ))["ControlPoints"];

				using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("ControlPoints"))
				{
					primaryShape.ControlPoints = oldCtrlPoints;
					propControlPoints.SetValue( primaryShape, newCtrlPoints);
					
					IControlPointDesigner cpd = _rootDesigner.GetControlPointDesigner( primaryShape);
					if( cpd != null) cpd.EndEditControlPoints( );
					a.EndEditControlPoint();
					tx.Commit();
				}
			}


			foreach( Shape shape in _rootDesigner.ShapeContainer.Shapes) shape.UnlockRotation();

			//a.EndEditControlPoint();MUst be set during the transaction...See above..!

			CommitDragShapeAttributes();
		}

		private void CommitEditPoints()
		{
			if (_dragDropData == null) return;

			VectorShape primaryShape = _dragDropData.PrimaryAttributes.Shape as VectorShape;

			if( primaryShape == null) return;

			ShapeAdornment a = Adornment( primaryShape );
			int editingIndices = a.EditingPointIndices;

			if( editingIndices == -1) return;

			AnchorPoint[] newCtrlPoints = primaryShape.Points;
			AnchorPoint[] oldCtrlPoints = _dragDropData.PrimaryAttributes.Points;
			if( oldCtrlPoints[ editingIndices] != newCtrlPoints[ editingIndices]) 
			{
				PropertyDescriptor	propPoints		= TypeDescriptor.GetProperties(typeof( VectorShape ))["Points"];

				using ( DesignerTransaction tx = _rootDesigner.DesignerHost.CreateTransaction("Points"))
				{
					primaryShape.Points = oldCtrlPoints;
					propPoints.SetValue( primaryShape, newCtrlPoints);
					tx.Commit();
				}
			}

			foreach( Shape shape in _rootDesigner.ShapeContainer.Shapes) shape.UnlockRotation();
			a.EndEditPoint();
			CommitDragShapeAttributes();
		}

		private void CommitSelectionRectangle( Point mouseUpTransformed )
		{
			//FileWatcher.WriteLine("CommitSelectionRectangle called");

			if (_dragDropData == null) return;

			//Select component if located in the selection rectangle
			//-----------------------------------------------------------------------------------------------
			ShapeCollection shapes = _rootDesigner.ShapeContainer.Shapes;
			Rectangle selectionRect = GetPointsBounds(  _dragDropData.LastMouseDown, mouseUpTransformed);
			if( shapes != null && shapes.Count > 0 )
			{
				ArrayList list = new ArrayList();
				foreach( Shape shape in shapes )
					if ( shape.Site != null && selectionRect.Contains( Rectangle.Truncate(shape.GetPathBounds())))
						list.Add( shape);

				if( list.Count > 0)	_rootDesigner.SetSelectedComponents( list, SelectionTypes.Primary);// SelectionTypes.Click);
			}

			Invalidate( false );
			_dragDropData = null;

		}

		#endregion MOUSE-UP COMMITS

		#region MOUSE EVENTS

		protected CursorStatus GetProviderCursorStatus( Point point, bool transform )
		{
			
			if( transform ) point	= TransformPoint( point );

			if( _pathCpX.IsVisible( point )) return CursorStatus.Bottom;
			if( _pathCpY.IsVisible( point )) return CursorStatus.Right;
			if( _pathCpXY.IsVisible( point)) return CursorStatus.BottomRight;

			return CursorStatus.None;
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			
			try
			{
				if( _rootDesigner == null ) return;



				Point pt			= new Point( e.X, e.Y);
				Point ptTransform	= TransformPoint( pt );
				Shape hitShape	= null;

				CursorStatus cursorStatus    = GetProviderCursorStatus( ptTransform, false  );//new
				
				if( cursorStatus == CursorStatus.None)//new
				cursorStatus	= this.GetCursorStatus( ptTransform,false, out hitShape );

				//------------------------------------------------------------------------------------------------------------
				//Check selected components
				//------------------------------------------------------------------------------------------------------------
				ISelectionService ss = _rootDesigner.SelectionService;
				IList selectedShapes = (IList)ss.GetSelectedComponents();

				Shape primaryShape = ss.PrimarySelection as Shape;
				ShapeAdornment primaryAdornment = Adornment( primaryShape );//NEW:03.10.2005

				if(primaryAdornment != null && primaryAdornment.PointsEditingMode ) 
				{
					//if( hitShape != primaryShape ) cursorStatus = CursorStatus.None;
					primaryAdornment.LastHitTest = ptTransform;
					if( hitShape != primaryShape) return;
				}
				else if( hitShape != null)
				{
					if( hitShape == _rootDesigner.ShapeContainer || selectedShapes.Contains( _rootDesigner.ShapeContainer) )
						ss.SetSelectedComponents( new Shape[]{ hitShape }, SelectionTypes.Replace);
					else
					{
                        ss.SetSelectedComponents(new Shape[] { hitShape }, SelectionTypes.Primary);//SelectionTypes.Click);
						if( ss.SelectionCount == 0 )
							ss.SetSelectedComponents( new IComponent[]{ _rootDesigner.Component }, SelectionTypes.Replace/*Click*/ );
					}
				}
				else ss.SetSelectedComponents( new IComponent[]{ _rootDesigner.Component }, SelectionTypes.Replace);
				//------------------------------------------------------------------------------------------------------------
				
				ResetRulerRanges();

				if( e.Button == MouseButtons.Right)
				{
					_dragDropData = null;
					this.Cursor = Cursors.Default;
					return;	
				}


				_dragDropData								= new DragDropData();
				//_dragDropData.Effect						= DragDropData.DragEffect.DrawSelectionRectangle;//Default
				_dragDropData.CursorStatus					= cursorStatus;//New:Old-->CursorStatus.None;
				_dragDropData.LastMouseDown					= ptTransform; 
				_dragDropData.CurrentMousePosition			= ptTransform; 
				_dragDropData.LastContainerProviderSize		= _rootDesigner.ShapeContainerProvider.Size;

			
				if( hitShape == null) return;
				if( hitShape == _rootDesigner.ShapeContainer && cursorStatus == CursorStatus.MouseOver) return;


				_dragDropData.PrimaryAttributes		= new ShapeAttributes( hitShape );



				//MOUSE OVER ---------------------------------------------------------------------
				if( cursorStatus == CursorStatus.MouseOver )
					_dragDropData.Effect				= DragDropData.DragEffect.Move;
					//ROTATE -------------------------------------------------------------------------
				else if( cursorStatus == CursorStatus.Rotation )
					_dragDropData.Effect				= DragDropData.DragEffect.Rotation;
					//SCALE --------------------------------------------------------------------------
				else if( cursorStatus == CursorStatus.ScaleLeft )
					_dragDropData.Effect				= DragDropData.DragEffect.ScaleLeft;
				else if( cursorStatus == CursorStatus.ScaleTop)
					_dragDropData.Effect				= DragDropData.DragEffect.ScaleTop;
				else if( cursorStatus == CursorStatus.ScaleRight )
					_dragDropData.Effect				= DragDropData.DragEffect.ScaleRight;
				else if( cursorStatus == CursorStatus.ScaleBottom)
					_dragDropData.Effect				= DragDropData.DragEffect.ScaleBottom;
					//WARP ----------------------------------------------------------------------------
				else if( cursorStatus == CursorStatus.WarpBottomLeft)
					_dragDropData.Effect				= DragDropData.DragEffect.WarpBottomLeft;
				else if( cursorStatus == CursorStatus.WarpBottomRight)
					_dragDropData.Effect				= DragDropData.DragEffect.WarpBottomRight;
				else if( cursorStatus == CursorStatus.WarpTopLeft)
					_dragDropData.Effect				= DragDropData.DragEffect.WarpTopLeft;
				else if( cursorStatus == CursorStatus.WarpTopRight)
					_dragDropData.Effect				= DragDropData.DragEffect.WarpTopRight;
					//----------------------------------------------------------------------
				else if( cursorStatus == CursorStatus.WarpBottom)
					_dragDropData.Effect				= DragDropData.DragEffect.WarpBottom;
				else if( cursorStatus == CursorStatus.WarpRight)
					_dragDropData.Effect				= DragDropData.DragEffect.WarpRight;
				else if( cursorStatus == CursorStatus.WarpLeft)
					_dragDropData.Effect				= DragDropData.DragEffect.WarpLeft;
				else if( cursorStatus == CursorStatus.WarpTop)
					_dragDropData.Effect				= DragDropData.DragEffect.WarpTop;
					//SHEAR --------------------------------------------------------------------------
				else if( cursorStatus == CursorStatus.ShearX)
					_dragDropData.Effect				= DragDropData.DragEffect.ShearX;
				else if( cursorStatus == CursorStatus.ShearY)
					_dragDropData.Effect				= DragDropData.DragEffect.ShearY;
					//Edit control points --------------------------------------------------------------------------
				else if( cursorStatus == CursorStatus.EditControlPoints)
				{
					_dragDropData.Effect = DragDropData.DragEffect.EditControlPoints;
					IControlPointDesigner cpd = _rootDesigner.GetControlPointDesigner( hitShape );
					if( cpd != null) cpd.BeginEditControlPoints( );

				}
					//Edit free shape points --------------------------------------------------------------------------
				else if( cursorStatus == CursorStatus.EditPoints)
					_dragDropData.Effect = DragDropData.DragEffect.EditPoints;
					//RESIZE --------------------------------------------------------------------------
				else 
					_dragDropData.Effect				= DragDropData.DragEffect.Resize;


				//FileWatcher.WriteLine("MouseDown effect:"+ _dragDropData.Effect.ToString());

				_dragShapeAttributes = new Hashtable();

				selectedShapes = (IList)ss.GetSelectedComponents();//Again to get new changes!!!
				foreach( object shapeObject in selectedShapes ) 
					if( shapeObject is Shape )
					{
						Shape shape = (Shape)shapeObject;
						ShapeAttributes att = new ShapeAttributes( shape );
						_dragShapeAttributes.Add( shape, att);
					}
					
				foreach( Shape shape in _rootDesigner.ShapeContainer.Shapes) 
					if( shape.Site != null && !ss.GetComponentSelected( shape ) )
						_dragShapeAttributes.Add( shape, new ShapeAttributes( shape));

				if( hitShape != _rootDesigner.ShapeContainer)
				{
					bool lockRotationPoint = _dragDropData.Effect == DragDropData.DragEffect.Resize ||
						_dragDropData.Effect == DragDropData.DragEffect.EditControlPoints ||
						_dragDropData.Effect == DragDropData.DragEffect.EditPoints;

					if( lockRotationPoint )	
						foreach( Shape shape in _rootDesigner.ShapeContainer.Shapes)
							shape.LockRotation();

					//---------------------------------------------------------------------------------------
					if(selectedShapes.Count > 1 && _dragDropData.Effect == DragDropData.DragEffect.Rotation )	
						_dragDropData.RotationAnchor = hitShape.GetRotatingPoint();
					//---------------------------------------------------------------------------------------
				}

				_dragDropData.CurrentMousePosition = this.SnapGridPoint( _dragDropData.CurrentMousePosition );


			}
			catch( Exception exc)
			{
				//FileWatcher.WriteLine("OnMouseDown:"+ exc.Message);
				throw exc;
			}
			finally
			{
				this.Invalidate( true );
				UpdateMenuStatus();
				this.Focus();

			}


		}


		protected override void OnMouseUp(MouseEventArgs e)
		{
			this.Cursor = Cursors.Default;

			try
			{
				if( _rootDesigner == null ) return;

				Point pt			= new Point( e.X, e.Y);
				Point ptTransform	= TransformPoint( pt );

				if( e.Button == MouseButtons.Right)
				{	ShowContextMenu( pt );	return;	}

				if (_dragDropData == null) return;
					

				if( _dragDropData.Effect == DragDropData.DragEffect.DrawSelectionRectangle || _dragDropData.LastMouseDown == ptTransform )
				{	CommitSelectionRectangle(ptTransform);	return;	}



				if( _dragDropData.Effect == DragDropData.DragEffect.ScaleLeft || 
					_dragDropData.Effect == DragDropData.DragEffect.ScaleRight||
					_dragDropData.Effect == DragDropData.DragEffect.ScaleTop||
					_dragDropData.Effect == DragDropData.DragEffect.ScaleBottom)
				{	CommitScale();	return;	}

				if( _dragDropData.Effect == DragDropData.DragEffect.WarpBottomLeft || 
					_dragDropData.Effect == DragDropData.DragEffect.WarpBottomRight||
					_dragDropData.Effect == DragDropData.DragEffect.WarpTopLeft ||
					_dragDropData.Effect == DragDropData.DragEffect.WarpTopRight ||
					//--------------------------------------------------------
					_dragDropData.Effect == DragDropData.DragEffect.WarpLeft||  
					_dragDropData.Effect == DragDropData.DragEffect.WarpRight ||
					_dragDropData.Effect == DragDropData.DragEffect.WarpBottom || 
					_dragDropData.Effect == DragDropData.DragEffect.WarpTop	)
				{	CommitWarp();	return;	}

				if( _dragDropData.Effect == DragDropData.DragEffect.Rotation)
				{	CommitRotate();	return;	}

				if( _dragDropData.Effect == DragDropData.DragEffect.ShearX || 
					_dragDropData.Effect == DragDropData.DragEffect.ShearY )
				{	CommitShear();	return;	}

				if( _dragDropData.Effect == DragDropData.DragEffect.Move || _dragDropData.Effect == DragDropData.DragEffect.Resize)
				{	CommitResize();	return;	}

				if( _dragDropData.Effect == DragDropData.DragEffect.EditControlPoints)
				{	CommitEditControlPoints();	return;	}

				if( _dragDropData.Effect == DragDropData.DragEffect.EditPoints)
				{	CommitEditPoints();	return;	}

			}
			catch( Exception exc)
			{
				//FileWatcher.WriteLine("OnMouseUp:"+ exc.Message);
				throw exc;
			}
		}


		protected override void OnMouseMove(MouseEventArgs e)
		{
			try
			{
				if( _rootDesigner == null) return;

				Point pt = new Point( e.X, e.Y);

				bool dragging = e.Button == MouseButtons.Left && _dragDropData != null;

				if (!dragging )//Not dragging...Then set mouse state
				{
					Shape selected = null;
					//CursorStatus cursorStatus = this.GetCursorStatus( pt, out selected );
					
					CursorStatus cursorStatus = GetProviderCursorStatus( pt , true);//new
				
					if( cursorStatus == CursorStatus.None)//new
						cursorStatus	= this.GetCursorStatus( pt, out selected );

					ISelectionService ss = _rootDesigner.SelectionService;

					if( ss == null) cursorStatus = CursorStatus.None;
					else
					{
						Shape primaryShape = ss.PrimarySelection as Shape;
						ShapeAdornment a = this.Adornment( primaryShape );
						if(a != null && a.PointsEditingMode && selected != primaryShape )
							cursorStatus = CursorStatus.None;
						else if( _rootDesigner.ShapeContainer == selected && cursorStatus == CursorStatus.MouseOver)
							cursorStatus = CursorStatus.None;
					}

					this.Cursor = ShapeAdornment.GetCursor( cursorStatus );
					
					return;


				}
				
				//Dragging...
				//--------------------------------------------------------------------------------------
				if( _dragDropData.Effect == DragDropData.DragEffect.DrawSelectionRectangle)
				{
					Point ptTransform	= TransformPoint( pt );
					if( _dragDropData.CurrentMousePosition == ptTransform ) return;

					Rectangle invalidateBounds = GetPointsBounds( _dragDropData.LastMouseDown, _dragDropData.CurrentMousePosition, ptTransform);
					_dragDropData.CurrentMousePosition	= ptTransform;
					InvalidateExact( invalidateBounds );

				}
				else if( _dragDropData.Effect == DragDropData.DragEffect.Move || 
					_dragDropData.Effect == DragDropData.DragEffect.Resize || 
					//-------------------------------------------------------------
					_dragDropData.Effect == DragDropData.DragEffect.ScaleLeft || 
					_dragDropData.Effect == DragDropData.DragEffect.ScaleRight || 
					_dragDropData.Effect == DragDropData.DragEffect.ScaleTop || 
					_dragDropData.Effect == DragDropData.DragEffect.ScaleBottom || 
					//-------------------------------------------------------------
					_dragDropData.Effect == DragDropData.DragEffect.WarpBottomLeft|| 
					_dragDropData.Effect == DragDropData.DragEffect.WarpBottomRight || 
					_dragDropData.Effect == DragDropData.DragEffect.WarpTopLeft || 
					_dragDropData.Effect == DragDropData.DragEffect.WarpTopRight || 
					//--------------------------------------------------------------
					_dragDropData.Effect == DragDropData.DragEffect.WarpLeft||  
					_dragDropData.Effect == DragDropData.DragEffect.WarpRight ||
					_dragDropData.Effect == DragDropData.DragEffect.WarpBottom || 
					_dragDropData.Effect == DragDropData.DragEffect.WarpTop ||
					//-------------------------------------------------------------
					_dragDropData.Effect == DragDropData.DragEffect.ShearX ||
					_dragDropData.Effect == DragDropData.DragEffect.ShearY ||
					//-------------------------------------------------------------
					_dragDropData.Effect == DragDropData.DragEffect.EditControlPoints ||
					_dragDropData.Effect == DragDropData.DragEffect.EditPoints ||
					//-------------------------------------------------------------
					_dragDropData.Effect == DragDropData.DragEffect.Rotation )
				{
					if( pt.X <= 0 ) pt.X = 0;
					if( pt.Y <= 0 ) pt.Y = 0;

					Point ptTransform =this.TransformPoint( pt, _snapToGrid);

					if( _dragDropData.CurrentMousePosition == ptTransform ) return;

					Point offset = new Point( 0,0 );
					offset.X = ptTransform.X - _dragDropData.CurrentMousePosition.X;
					offset.Y = ptTransform.Y - _dragDropData.CurrentMousePosition.Y;
					_dragDropData.CurrentMousePosition	= ptTransform;

					if( _dragDropData.Effect == DragDropData.DragEffect.Move )
						OnMoveShapes( offset );
					else if( _dragDropData.Effect == DragDropData.DragEffect.Resize )
						OnResizeShapes(offset);
					else if( _dragDropData.Effect == DragDropData.DragEffect.Rotation )
						OnRotateShapes(  );
					else if( _dragDropData.Effect == DragDropData.DragEffect.ScaleLeft ||  
							_dragDropData.Effect == DragDropData.DragEffect.ScaleRight ||
							_dragDropData.Effect == DragDropData.DragEffect.ScaleTop || 
							_dragDropData.Effect == DragDropData.DragEffect.ScaleBottom )
						OnScaleShapes( offset );
					else if( _dragDropData.Effect == DragDropData.DragEffect.ShearX || 
							_dragDropData.Effect == DragDropData.DragEffect.ShearY)
						OnShearShapes( offset );
					else if
						( 	_dragDropData.Effect == DragDropData.DragEffect.WarpBottomLeft||  
							_dragDropData.Effect == DragDropData.DragEffect.WarpBottomRight ||
							_dragDropData.Effect == DragDropData.DragEffect.WarpTopLeft || 
							_dragDropData.Effect == DragDropData.DragEffect.WarpTopRight ||
							//-------------------------------------------------------------------
							_dragDropData.Effect == DragDropData.DragEffect.WarpLeft||  
							_dragDropData.Effect == DragDropData.DragEffect.WarpRight ||
							_dragDropData.Effect == DragDropData.DragEffect.WarpBottom || 
							_dragDropData.Effect == DragDropData.DragEffect.WarpTop )
						OnWarpShapes( offset );
					else if( _dragDropData.Effect == DragDropData.DragEffect.EditControlPoints)
						OnEditControlPoints( offset);
					else if( _dragDropData.Effect == DragDropData.DragEffect.EditPoints)
						OnEditPoints( offset);

				}


			}
			catch( Exception exc )
			{
				FileWatcher.WriteLine("OnMouseMove:"+ exc.StackTrace);
				throw exc;
			}
		}


		#endregion MOUSE EVENTS

		#region DRAG AND DROP
		private bool _drawFrameOnDragLeave		= false;

		private Rectangle _reversibleRectangle	= new Rectangle(0,0,100,100);
		private void DrawReversibleRectangle(  )
		{
			if( _rootDesigner == null ) return;

			ControlPaint.DrawReversibleFrame(  _reversibleRectangle, Color.Black, FrameStyle.Thick );
			_drawFrameOnDragLeave = true;
		}


		protected override void OnDragDrop(DragEventArgs e)
		{//Object dropped...
			base.OnDragDrop(e);
			try
			{
				if( _rootDesigner == null ) return;

				IToolboxService ts = _rootDesigner.ToolBoxService;
				IDesignerHost host = _rootDesigner.DesignerHost;

				if( ts.IsToolboxItem(e.Data, host))
				{
					ToolboxItem tbi = ts.DeserializeToolboxItem(e.Data, host);
					Point ptTransform = this.TransformPoint( PointToClient( new Point( e.X,e.Y)), _snapToGrid);
					_rootDesigner.AddToolItem( tbi , ptTransform, this.TransformPoint( PointToClient( new Point( e.X,e.Y))) );

					Type type = Type.GetType(tbi.TypeName);
					if( type != null && type.IsSubclassOf( typeof(Shape))) DrawReversibleRectangle(  );

				}

				Invalidate(false);
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("OnDragDrop error:"+ exc.Message);
				throw exc;
			}
		}


		protected override void OnDragEnter(DragEventArgs e)
		{
			try
			{
				base.OnDragEnter (e);

				// Is this a toolbox item that is being dropped?
				if( _rootDesigner == null) return;
				
		
				IDesignerHost host = _rootDesigner.DesignerHost;
				IToolboxService ts = _rootDesigner.ToolBoxService;
				if (ts != null && host != null && ts.IsToolboxItem(e.Data, host))
				{
					ToolboxItem tbi = ts.DeserializeToolboxItem( e.Data ) as ToolboxItem;
					Type type = Type.GetType(tbi.TypeName);
					if( type != null && type.IsSubclassOf( typeof(Shape)))
					{
						Point ptTransform	= Control.MousePosition ;
						_reversibleRectangle.Location = ptTransform;
						DrawReversibleRectangle(  );
					}

					e.Effect = DragDropEffects.Copy;

				}
				else e.Effect = DragDropEffects.None;

				
				
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("OnDragEnter error:"+ exc.Message);
				throw exc;
			}

		}
		
		
		protected override void OnDragOver(DragEventArgs e)
		{
			try
			{
				base.OnDragOver (e);
				if( _rootDesigner == null) return;


			
				IDesignerHost host = _rootDesigner.DesignerHost;
				IToolboxService ts = _rootDesigner.ToolBoxService;
				if (ts != null && host != null && ts.IsToolboxItem(e.Data, host))
				{
					ToolboxItem tbi = ts.DeserializeToolboxItem( e.Data ) as ToolboxItem;
					Type type = Type.GetType(tbi.TypeName);
					if( type != null && type.IsSubclassOf( typeof(Shape)))
					{
						DrawReversibleRectangle(  );
						Point ptTransform	= Control.MousePosition ;
						_reversibleRectangle.Location = ptTransform;
						DrawReversibleRectangle(  );
					}
				}

			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("OnDragOver error:"+ exc.Message);
				throw exc;
			}
		}


		protected override void OnDragLeave(EventArgs e)
		{
			try
			{
				base.OnDragLeave (e);
				if( _rootDesigner == null ) return;

				if( _drawFrameOnDragLeave )	DrawReversibleRectangle(  );
				_drawFrameOnDragLeave = false;
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("OnDragLeave error:"+ exc.Message);
				throw exc;
			}

		}


		
		#endregion DRAG AND DROP

		protected override void OnPaint(PaintEventArgs e)
		{

			if( _rootDesigner == null) return;
			IShapeContainerProvider scp = _rootDesigner.ShapeContainerProvider;
			if( scp == null) return;
			ShapeContainer sc = scp.ShapeContainer;
			if( sc == null) return;

			Graphics g = e.Graphics;
//			g.ScaleTransform( 5f,5f);
			GraphicsContainer gc = g.BeginContainer();
			try
			{
				Point scrollPosition	= this.AutoScrollPosition;
				g.SmoothingMode = SmoothingMode.AntiAlias;
				g.Clip= new Region( this.ClientRectangle);
				g.TranslateTransform( (float)scrollPosition.X , (float)scrollPosition.Y);
				//----------------------------------------------------------------
				// Paint Shapes
				//----------------------------------------------------------------
				sc.Paint(g);

				//-------------------------------------------------------------------------------------------------------------
				// Mouse is being dragged? Then draw selection rectangle
				//-------------------------------------------------------------------------------------------------------------
				if( _dragDropData != null && _dragDropData.Effect == DragDropData.DragEffect.DrawSelectionRectangle)
				{
					Rectangle rect = GetPointsBounds( _dragDropData.CurrentMousePosition, _dragDropData.LastMouseDown);

					using (SolidBrush backgbrush = new SolidBrush( Color.FromArgb( 48, Color.CornflowerBlue)))
						g.FillRectangle( backgbrush, rect);

					g.DrawRectangle( Pens.CornflowerBlue, rect);
				}
				//----------------------------------------------------------------------------------
				//Otherwise draw shape adornments, if any selected.
				//----------------------------------------------------------------------------------
				ISelectionService ss = _rootDesigner.SelectionService;
				if( ss == null || ss.SelectionCount == 0 ) return;

				ICollection selectedComponents = ss.GetSelectedComponents();
				foreach( object shapeObject in selectedComponents ) 
					if( shapeObject is Shape && shapeObject != sc )
					{
						Shape shape = (Shape)shapeObject;
						ShapeAdornment a = Adornment( shape );

						if( a != null) a.DrawAdornments(g);
					}

				//----------------------------------------------------------------------------------
				// Draw Clip Background
				//----------------------------------------------------------------------------------
				Rectangle clientRect = this.ClientRectangle;
				
				RectangleF containerRect = sc.Bounds;
				if( sc != scp) containerRect = new RectangleF( Point.Empty, scp.Size );
				containerRect.Height++;
				containerRect.Width++;


				using(Region reg = new Region( new Rectangle(new Point(0,0), this.AutoScrollMinSize) ))
				{
					reg.Exclude( containerRect );
					using(SolidBrush clipBrush = new SolidBrush( Color.FromArgb( 64, Color.RoyalBlue)))//44
					g.FillRegion(clipBrush, reg);
				}

				//----------------------------------------------------------------------------------
				// DRAW CONTAINER ADORNMENTS
				//----------------------------------------------------------------------------------
				ShapeAdornment ad = Adornment( sc );
				if( ad.IsSelected ) ad.DrawAdornments( g );
				


			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("RulingPanel:OnPaint:"+ exc.Message);
				FileWatcher.WriteLine("RulingPanel:OnPaint:"+ exc.StackTrace);

				//throw exc;
			}
			finally
			{
				g.EndContainer( gc);
				if(_drawGrid) PaintGrid(g);
				PaintContainerProviderAdornment( g );

			}

		}

		GraphicsPath _pathCpX	= new GraphicsPath();
		GraphicsPath _pathCpY	= new GraphicsPath();
		GraphicsPath _pathCpXY	= new GraphicsPath();


		protected void PaintContainerProviderAdornment( Graphics g)
		{

			Point scrollPosition	= this.AutoScrollPosition;

			GraphicsContainer container = g.BeginContainer();

			g.CompositingQuality = CompositingQuality.HighSpeed;
			g.PixelOffsetMode= PixelOffsetMode.HighSpeed;

			// Shift the background 
			g.TranslateTransform( (float)scrollPosition.X , (float)scrollPosition.Y);

			try
			{


				IShapeContainerProvider scp = _rootDesigner.ShapeContainerProvider;
				if( scp == null) return;

				if( scp.ShapeContainer == scp ) return;

				if( _rootDesigner.SelectionService.PrimarySelection != scp ) return;


				_pathCpX.Reset();
				_pathCpY.Reset();
				_pathCpXY.Reset();

				Size scpSize = scp.Size;


				using (HatchBrush penBrush = new HatchBrush( HatchStyle.SmallCheckerBoard, Color.Blue, Color.Transparent))
				using ( Pen pen = new Pen(penBrush, 7 ))
				{

					int offset = 3;
					Point bottomLeft	= new Point( 0, scp.Size.Height + offset);
					Point bottomRight	= new Point( scp.Size.Width + offset, scp.Size.Height + offset);
					Point topRight		= new Point( scp.Size.Width + offset,0);
					g.DrawLines( pen, new Point[]{ bottomLeft, bottomRight, topRight});

					using ( SolidBrush gripBrush = new SolidBrush( Color.White ))
					using ( Pen gripPen = new Pen( Color.Black, 1 ))
					{
						bottomLeft.X+=  scpSize.Width/2; bottomLeft.Y-=offset;
						topRight.Y+= scpSize.Height/2;topRight.X -= offset;
						bottomRight.X-=offset;bottomRight.Y-=offset;

						Size  gripSize = new Size(7,7); 
						Rectangle rectX		= new Rectangle(bottomLeft, gripSize);
						Rectangle rectY		= new Rectangle(topRight, gripSize);
						Rectangle rectXY	= new Rectangle(bottomRight, gripSize);
					
						_pathCpX.AddRectangle( rectX );g.FillPath(gripBrush, _pathCpX );g.DrawPath(gripPen, _pathCpX );
						_pathCpY.AddRectangle( rectY );g.FillPath( gripBrush,_pathCpY );g.DrawPath(gripPen,_pathCpY );
						_pathCpXY.AddRectangle( rectXY );g.FillPath( gripBrush,_pathCpXY );g.DrawPath(gripPen,_pathCpXY );
					}
				}


			}
			finally
			{
				g.EndContainer( container);
			}



		}

		public enum PaintGridArg
		{
			Vertical,
			Horizontal,
			Both
		}

		private void PaintGrid(Graphics g)
		{
			this.PaintGrid( g, PaintGridArg.Both , this.Size);
		}

		protected internal void PaintGrid(Graphics g, PaintGridArg arg, Size size)
		{
			Point scrollPosition	= this.AutoScrollPosition;
			Size  scrollMinSize		= this.AutoScrollMinSize;

			GraphicsContainer container = g.BeginContainer();


			try
			{

				g.CompositingQuality = CompositingQuality.HighSpeed;
				g.PixelOffsetMode= PixelOffsetMode.HighSpeed;

				// Shift the background 
				g.TranslateTransform( (float)scrollPosition.X , (float)scrollPosition.Y);


				int gridWidth	= _gridSize.Width;
				int gridHeight  = _gridSize.Height;

	
				Size scrollSize = new Size(0,0);
				scrollSize.Height = scrollMinSize.Height > size.Height ? scrollMinSize.Height: size.Height ;
				scrollSize.Width  = scrollMinSize.Width > size.Width ? scrollMinSize.Width : size.Width;
			
				int hLines = scrollSize.Height  / gridHeight;
				int vLines = scrollSize.Width   / gridWidth;

				if( arg == PaintGridArg.Both || arg == PaintGridArg.Horizontal)
				for( int i=1; i <= hLines; i++ )
				{	
					Pen pen = (i % _gridPageSize) == 0 ? _linePenBold:_linePenBase;
					g.DrawLine(pen, 0, i*gridHeight, scrollSize.Width , i*gridHeight);
				}

				if( arg == PaintGridArg.Both || arg == PaintGridArg.Vertical)
				for( int i=1; i <= vLines; i++ )
				{	
					Pen pen = (i % _gridPageSize) == 0 ? _linePenBold:_linePenBase;
					g.DrawLine(pen, i*gridWidth, 0, i*gridWidth, scrollSize.Height );
				}

			}
			catch( Exception e)
			{
				FileWatcher.WriteLine("RulingPanel::PaintGrid failed"+e.Message);
			}
			finally
			{
				g.EndContainer( container);
			}

		}



		private const int WM_HSCROLL = 0x114;
		private const int WM_VSCROLL = 0x115;

		bool _rulerInvalidating = false;
		protected override void WndProc(ref Message msg)
		{
			if(_rulerInvalidating ) return;

			try
			{
				_rulerInvalidating = true;

				// Look for the WM_VSCROLL or the WM_HSCROLL messages.
				if( _hRuler != null && msg.Msg == WM_HSCROLL ){ _hRuler.Invalidate();}
				if (_vRuler != null && msg.Msg == WM_VSCROLL ){ _vRuler.Invalidate();}
			}
			finally
			{
				_rulerInvalidating = false;
			}

			// Pass message to default handler.
			base.WndProc(ref msg);
		}


	}


}
